web-dev-qa-db-fra.com

Équivalent de Paste R to Python

Je suis un nouvel afficionado python. Pour les utilisateurs de R, il existe une fonction: coller qui permet de concaténer deux ou plusieurs variables dans un cadre de données. C'est très utile. Par exemple Supposons que j'ai cette dataframe:

   categorie titre tarifMin  lieu  long   lat   img dateSortie
1      Zoo,  Aquar      0.0 Aquar 2.385 48.89 ilo,0           
2      Zoo,  Aquar      4.5 Aquar 2.408 48.83 ilo,0           
6      lieu  Jardi      0.0 Jardi 2.320 48.86 ilo,0           
7      lieu  Bois       0.0 Bois  2.455 48.82 ilo,0           
13     espac Canal      0.0 Canal 2.366 48.87 ilo,0           
14     espac Canal     -1.0 Canal 2.384 48.89 ilo,0           
15     parc  Le Ma     20.0 Le Ma 2.353 48.87 ilo,0 

Je veux créer une nouvelle colonne qui utilise une autre colonne dans un cadre de données et du texte. Avec R, je fais: 

> y$thecolThatIWant=ifelse(y$tarifMin!=-1,
+                             paste("Evenement permanent  -->",y$categorie,
+                                   y$titre,"C  partir de",y$tarifMin,"€uros"),
+                             paste("Evenement permanent  -->",y$categorie,
+                                   y$titre,"sans prix indique"))

Et le résultat est:

> y
   categorie titre tarifMin  lieu  long   lat   img dateSortie
1      Zoo,  Aquar      0.0 Aquar 2.385 48.89 ilo,0           
2      Zoo,  Aquar      4.5 Aquar 2.408 48.83 ilo,0           
6      lieu  Jardi      0.0 Jardi 2.320 48.86 ilo,0           
7      lieu  Bois       0.0 Bois  2.455 48.82 ilo,0           
13     espac Canal      0.0 Canal 2.366 48.87 ilo,0           
14     espac Canal     -1.0 Canal 2.384 48.89 ilo,0           
15     parc  Le Ma     20.0 Le Ma 2.353 48.87 ilo,0           
                                                thecolThatIWant
1  Evenement permanent  --> Zoo,  Aquar C  partir de  0.0 €uros
2  Evenement permanent  --> Zoo,  Aquar C  partir de  4.5 €uros
6  Evenement permanent  --> lieu  Jardi C  partir de  0.0 €uros
7  Evenement permanent  --> lieu  Bois  C  partir de  0.0 €uros
13 Evenement permanent  --> espac Canal C  partir de  0.0 €uros
14 Evenement permanent  --> espac Canal C  partir de -1.0 €uros
15 Evenement permanent  --> parc  Le Ma C  partir de 20.0 €uros

Ma question est la suivante: comment puis-je faire la même chose avec les Pandas Python ou d’autres modules?

Ce que j'ai essayé jusqu'à présent: Eh bien, je suis un très nouveau. Désolé pour mon erreur. J'essaie de reproduire l'exemple en Python et nous supposons que je reçois quelque chose comme ça

table=pd.read_csv("y.csv",sep=",")
tt= table.loc[:,['categorie','titre','tarifMin','long','lat','lieu']]
table
ategorie    titre   tarifMin    long    lat     lieu
0   Zoo,    Aquar   0.0     2.385   48.89   Aquar
1   Zoo,    Aquar   4.5     2.408   48.83   Aquar
2   lieu    Jardi   0.0     2.320   48.86   Jardi
3   lieu    Bois    0.0     2.455   48.82   Bois
4   espac   Canal   0.0     2.366   48.87   Canal
5   espac   Canal   -1.0    2.384   48.89   Canal
6   parc    Le Ma   20.0    2.353   48.87   Le Ma

J'ai essayé cela fondamentalement

sc="Even permanent -->" + " "+ tt.titre+" "+tt.lieu
tt['theColThatIWant'] = sc
tt

Et j'ai eu ça

    categorie   titre   tarifMin    long    lat     lieu    theColThatIWant
0   Zoo,    Aquar   0.0     2.385   48.89   Aquar   Even permanent --> Aquar Aquar
1   Zoo,    Aquar   4.5     2.408   48.83   Aquar   Even permanent --> Aquar Aquar
2   lieu    Jardi   0.0     2.320   48.86   Jardi   Even permanent --> Jardi Jardi
3   lieu    Bois    0.0     2.455   48.82   Bois    Even permanent --> Bois Bois
4   espac   Canal   0.0     2.366   48.87   Canal   Even permanent --> Canal Canal
5   espac   Canal   -1.0    2.384   48.89   Canal   Even permanent --> Canal Canal
6   parc    Le Ma   20.0    2.353   48.87   Le Ma   Even permanent --> Le Ma Le Ma

Maintenant, je suppose que je dois boucler avec condition s'il n'y a pas de vectorisation comme dans R?

19
GjT

Voici une implémentation simple qui fonctionne sur les listes, et probablement d’autres iterables. Attention: cela n'a été que légèrement testé, et uniquement dans Python 3.5:

import functools
def reduce_concat(x, sep=""):
    return functools.reduce(lambda x, y: str(x) + sep + str(y), x)

def paste(*lists, sep=" ", collapse=None):
    result = map(lambda x: reduce_concat(x, sep=sep), Zip(*lists))
    if collapse is not None:
        return reduce_concat(result, sep=collapse)
    return list(result)

print(paste([1,2,3], [11,12,13], sep=','))
print(paste([1,2,3], [11,12,13], sep=',', collapse=";"))

# ['1,11', '2,12', '3,13']
# '1,11;2,12;3,13'

Vous pouvez également vous amuser davantage et reproduire d’autres fonctions telles que paste0:

paste0 = functools.partial(paste, sep="")
9
shadowtalker

Dans ce cas particulier, l'opérateur paste dans R est le plus proche de format de Python, qui a été ajouté dans Python 2.6. C'est plus récent et un peu plus flexible que l'ancien opérateur %.

Pour une réponse purement pythonique sans utiliser numpy ou pandas, voici une façon de le faire en utilisant vos données d'origine sous la forme d'une liste de listes (cela aurait également pu être fait sous forme de liste de dict, mais cela semblait plus encombré pour moi).

# -*- coding: utf-8 -*-
names=['categorie','titre','tarifMin','lieu','long','lat','img','dateSortie']

records=[[
    'Zoo',   'Aquar',     0.0,'Aquar',2.385,48.89,'ilo',0],[
    'Zoo',   'Aquar',     4.5,'Aquar',2.408,48.83,'ilo',0],[
    'lieu',  'Jardi',     0.0,'Jardi',2.320,48.86,'ilo',0],[
    'lieu',  'Bois',      0.0,'Bois', 2.455,48.82,'ilo',0],[
    'espac', 'Canal',     0.0,'Canal',2.366,48.87,'ilo',0],[
    'espac', 'Canal',    -1.0,'Canal',2.384,48.89,'ilo',0],[
    'parc',  'Le Ma',    20.0,'Le Ma', 2.353,48.87,'ilo',0] ]

def prix(p):
    if (p != -1):
        return 'C  partir de {} €uros'.format(p)
    return 'sans prix indique'

def msg(a):
    return 'Evenement permanent  --> {}, {} {}'.format(a[0],a[1],prix(a[2]))

[m.append(msg(m)) for m in records]

from pprint import pprint

pprint(records)

Le résultat est le suivant: 

[['Zoo',
  'Aquar',
  0.0,
  'Aquar',
  2.385,
  48.89,
  'ilo',
  0,
  'Evenement permanent  --> Zoo, Aquar C  partir de 0.0 \xe2\x82\xacuros'],
 ['Zoo',
  'Aquar',
  4.5,
  'Aquar',
  2.408,
  48.83,
  'ilo',
  0,
  'Evenement permanent  --> Zoo, Aquar C  partir de 4.5 \xe2\x82\xacuros'],
 ['lieu',
  'Jardi',
  0.0,
  'Jardi',
  2.32,
  48.86,
  'ilo',
  0,
  'Evenement permanent  --> lieu, Jardi C  partir de 0.0 \xe2\x82\xacuros'],
 ['lieu',
  'Bois',
  0.0,
  'Bois',
  2.455,
  48.82,
  'ilo',
  0,
  'Evenement permanent  --> lieu, Bois C  partir de 0.0 \xe2\x82\xacuros'],
 ['espac',
  'Canal',
  0.0,
  'Canal',
  2.366,
  48.87,
  'ilo',
  0,
  'Evenement permanent  --> espac, Canal C  partir de 0.0 \xe2\x82\xacuros'],
 ['espac',
  'Canal',
  -1.0,
  'Canal',
  2.384,
  48.89,
  'ilo',
  0,
  'Evenement permanent  --> espac, Canal sans prix indique'],
 ['parc',
  'Le Ma',
  20.0,
  'Le Ma',
  2.353,
  48.87,
  'ilo',
  0,
  'Evenement permanent  --> parc, Le Ma C  partir de 20.0 \xe2\x82\xacuros']]

Notez que bien que j'ai défini une liste names, elle n'est pas réellement utilisée. On pourrait définir un dictionnaire avec les noms des titres comme clé et le numéro de champ (à partir de 0) comme valeur, mais je ne me suis pas soucié de cela pour essayer de garder l'exemple simple.

Les fonctions prix et msg sont assez simples. La seule partie délicate est la compréhension de la liste [m.append(msg(m)) for m in records] qui parcourt tous les enregistrements et les modifie pour y ajouter votre nouveau champ, créé via un appel à msg.

4
Edward

Essayons les choses avec Apply.

df.apply( lambda x: str( x.loc[ desired_col ] ) + "pasting?" , axis = 1 )

vous recevrez des choses semblables comme de la pâte

1
胡亦朗
  1. Vous pouvez essayerpandas.Series.str.cat

    import pandas as pd
    def paste0(ss,sep=None,na_rep=None,):
        '''Analogy to R paste0'''
        ss = [pd.Series(s) for s in ss]
        ss = [s.astype(str) for s in ss]
        s = ss[0]
        res = s.str.cat(ss[1:],sep=sep,na_rep=na_rep)
        return res
    
    pasteA=paste0
    
  2. Ou simplement sep.join()

    #
    def paste0(ss,sep=None,na_rep=None, 
        castF=unicode, ##### many languages dont work well with str
    ):
        if sep is None:
            sep=''
        res = [castF(sep).join(castF(s) for s in x) for x in Zip(*ss)]
        return res
    pasteB = paste0
    
    
    %timeit pasteA([range(1000),range(1000,0,-1)],sep='_')
    # 100 loops, best of 3: 7.11 ms per loop
    %timeit pasteB([range(1000),range(1000,0,-1)],sep='_')
    # 100 loops, best of 3: 2.24 ms per loop
    
  3. J'ai utilisé itertools pour imiter le recyclage

    import itertools
    def paste0(ss,sep=None,na_rep=None,castF=unicode):
        '''Analogy to R paste0
        '''
        if sep is None:
            sep=u''
        L = max([len(e) for e in ss])
        it = itertools.izip(*[itertools.cycle(e) for e in ss])
        res = [castF(sep).join(castF(s) for s in next(it) ) for i in range(L)]
        # res = pd.Series(res)
        return res
    
  4. patsy pourrait être pertinent (utilisateur non expérimenté moi-même.)

1
shouldsee

ma réponse est vaguement basée sur la question originale, elle a été modifiée à partir de réponses données. Je voudrais illustrer les points suivants:

  • coller est% opérateur en python 
  • en appliquant vous pouvez créer une nouvelle valeur et l'assigner à une nouvelle colonne

pour les gens de R: il n’existe pas d’ifel sous forme directe (mais il existe des moyens de le remplacer correctement).

import numpy as np
import pandas as pd

dates = pd.date_range('20140412',periods=7)
df = pd.DataFrame(np.random.randn(7,4),index=dates,columns=list('ABCD'))
df['categorie'] = ['z', 'z', 'l', 'l', 'e', 'e', 'p']

def apply_to_row(x):
    ret = "this is the value i want: %f" % x['A']
    if x['B'] > 0:
        ret = "no, this one is better: %f" % x['C']
    return ret

df['theColumnIWant'] = df.apply(apply_to_row, axis = 1)
print df
1
lowtech

Si vous souhaitez simplement coller deux colonnes de chaîne ensemble, vous pouvez simplifier la réponse de @ shouldsee car vous n'avez pas besoin de créer la fonction. Par exemple, dans mon cas:

df['newcol'] = df['id_part_one'].str.cat(df['id_part_two'], sep='_')

Il peut être nécessaire que les deux séries soient de type object pour cela (je n'ai pas vérifié).

0
Corey Levinson

Cela fonctionne très bien comme la commande Coller dans R: R code:

 words = c("Here", "I","want","to","concatenate","words","using","pipe","delimeter")
 paste(words,collapse="|")

[1]

"Ici | je | veux | concaténer | mots | utiliser | tuyau | delimètre"

Python:

words = ["Here", "I","want","to","concatenate","words","using","pipe","delimeter"]
"|".join(words)

Résultat:

'Ici | je | veux | concaténer | mots | utiliser | tuyau | delimeter'

0
SAHIL BHANGE

Voici un exemple simple: comment y parvenir (si je ne suis pas porté, que voulez-vous faire):

import numpy as np
import pandas as pd

dates = pd.date_range('20130101',periods=6)
df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))
for row in df.itertuples():
    index, A, B, C, D = row
    print '%s Evenement permanent  --> %s , next data %s' % (index, A, B)

Sortie:

>>>df
                   A         B         C         D
2013-01-01 -0.400550 -0.204032 -0.954237  0.019025
2013-01-02  0.509040 -0.611699  1.065862  0.034486
2013-01-03  0.366230  0.805068 -0.144129 -0.912942
2013-01-04  1.381278 -1.783794  0.835435 -0.140371
2013-01-05  1.140866  2.755003 -0.940519 -2.425671
2013-01-06 -0.610569 -0.282952  0.111293 -0.108521

Cette boucle pour l'impression: 2013-01-01 00:00:00 Evénement permanent -> -0.400550121168, données suivantes -0.204032344442

2013-01-02 00:00:00 Evenement permanent  --> 0.509040318928 , next data -0.611698560541

2013-01-03 00:00:00 Evenement permanent  --> 0.366230438863 , next data 0.805067758304

2013-01-04 00:00:00 Evenement permanent  --> 1.38127775713 , next data -1.78379439485

2013-01-05 00:00:00 Evenement permanent  --> 1.14086631509 , next data 2.75500268167

2013-01-06 00:00:00 Evenement permanent  --> -0.610568516983 , next data -0.282952162792
0
Michał