Equivalente de Pasta R a Python
pandas paste (8)
Soy un nuevo aficionado a los pitones. Para los usuarios de R, hay una función: pegar que ayuda a concatenar dos o más variables en un marco de datos. Es muy útil. Por ejemplo, supongamos que tengo este marco de datos:
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
Quiero crear una nueva columna que use otra columna en un marco de datos y un texto. Con R, hago:
> 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"))
Y el resultado es:
> 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
Mi pregunta es: ¿Cómo puedo hacer lo mismo en Python Pandas o en algún otro módulo?
Lo que he intentado hasta ahora: bueno, soy un usuario muy nuevo. Lo siento mucho por mi error. Intento replicar el ejemplo en Python y suponemos que obtengo algo como esto
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
Yo intenté esto básicamente
sc="Even permanent -->" + " "+ tt.titre+" "+tt.lieu
tt[''theColThatIWant''] = sc
tt
Y tengo esto
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
Ahora, supongo que tengo que hacer un bucle con la condición si no hay vectorización como en R?
Puedes probar
pandas.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
O simplemente
#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
Lo he usado para imitar el reciclaje.
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
puede ser relevante (no soy un usuario experimentado).
Aquí hay una implementación simple que funciona en listas, y probablemente otros iterables. Advertencia: solo se ha probado ligeramente, y solo en 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''
También puedes divertirte más y replicar otras funciones como paste0
:
paste0 = functools.partial(paste, sep="")
Este es un ejemplo simple de cómo lograrlo (si no estoy desgastado, ¿qué desea hacer?):
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)
Salida:
>>>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
Esto que bucle para imprimir: 2013-01-01 00:00:00 Evenement permanente -> -0.400550121168, datos siguientes -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
Esto funciona mucho como el comando Pegar en el código R: R:
words = c("Here", "I","want","to","concatenate","words","using","pipe","delimeter")
paste(words,collapse="|")
[1]
"Aquí | Quiero | concatenar | palabras | utilizando | pipe | delimeter"
Pitón:
words = ["Here", "I","want","to","concatenate","words","using","pipe","delimeter"]
"|".join(words)
Resultado:
''Aquí | Quiero | concatenar | palabras | usando | pipe | delimeter''
Para este caso particular, el operador de paste
en R
es el más cercano al format
de Python que se agregó en Python 2.6. Es más nuevo y algo más flexible que el operador %
anterior.
Para una respuesta puramente Python-ic sin usar números o pandas, aquí hay una forma de hacerlo usando sus datos originales en forma de una lista de listas (esto también podría haberse hecho como una lista de dict, pero eso parecía más desordenado a mi).
# -*- 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)
El resultado es este:
[[''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'']]
Tenga en cuenta que aunque he definido una lista de names
en realidad no se utiliza. Uno podría definir un diccionario con los nombres de los títulos como clave y el número de campo (comenzando desde 0) como valor, pero no me molesté en esto para tratar de mantener el ejemplo simple.
Las funciones prix
y msg
son bastante simples. La única parte difícil es la comprensión de la lista [m.append(msg(m)) for m in records]
que se repite en todos los registros y modifica cada uno para agregar su nuevo campo, creado mediante una llamada a msg
.
Probemos cosas con aplique.
df.apply( lambda x: str( x.loc[ desired_col ] ) + "pasting?" , axis = 1 )
Recibirá cosas similares como pasta
Si solo desea pegar dos columnas de cadena, puede simplificar la respuesta de @ shouldsee porque no necesita crear la función. Por ejemplo, en mi caso:
df[''newcol''] = df[''id_part_one''].str.cat(df[''id_part_two''], sep=''_'')
Podría ser necesario que ambas Series sean de object
dtype para esto (no he verificado).
mi respuesta está basada libremente en la pregunta original, fue editada de la respuesta por woles. Me gustaría ilustrar los puntos:
- pegar es% operador en python
- Usando Apply puedes hacer un nuevo valor y asignarlo a una nueva columna.
para la gente de R: no hay ifelse en forma directa (pero hay maneras de reemplazarlo muy bien).
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