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?
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="")
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
.
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
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
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
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
patsy
pourrait être pertinent (utilisateur non expérimenté moi-même.)
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:
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
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é).
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'
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