agregue un prefijo de cadena a cada valor en una columna de cadena usando Pandas


119

Me gustaría agregar una cadena al inicio de cada valor en dicha columna de un marco de datos de pandas (elegantemente). Ya descubrí cómo hacer esto y actualmente estoy usando:

df.ix[(df['col'] != False), 'col'] = 'str'+df[(df['col'] != False), 'col']

Esto parece una cosa increíblemente poco elegante, ¿conoce alguna otra forma (que tal vez también agregue el carácter a las filas donde esa columna es 0 o NaN)?

En caso de que esto aún no esté claro, me gustaría convertir:

    col 
1     a
2     0

dentro:

       col 
1     stra
2     str0

¿Qué preguntas exactamente? por favor escriba una explicación sobre lo que hace su código / desearía que hiciera
Ryan Saxe

1
Pensé que lo que hace el código de ejemplo era muy claro para el usuario promedio de pandas. He agregado ejemplos de casos de uso para su conveniencia.
TheChymera

3
Su descripción está algo reñida con su código. ¿Qué pasa con el != Falsenegocio? ¿Quieres agregar stra todos los valores o solo a algunos?
BrenBarn

a cada valor, como se muestra en mis marcos de datos de ejemplo.
TheChymera

1
tu ejemplo aún no está claro, ¿quieres algo como df['col'] = 'str' + df['col'].astype(str)?
Roman Pekar

Respuestas:


223
df['col'] = 'str' + df['col'].astype(str)

Ejemplo:

>>> df = pd.DataFrame({'col':['a',0]})
>>> df
  col
0   a
1   0
>>> df['col'] = 'str' + df['col'].astype(str)
>>> df
    col
0  stra
1  str0

1
gracias. si es de interés, los índices de marcos de datos también admiten dichas manipulaciones de cadenas.
tagoma

2
¿Cómo hago esto si se deben cumplir las condiciones antes de la concatenación?
acecabana

1
@tagoma, después de 4 años, sí: también es compatible con los índices de marcos de datos. Puede crear una nueva columna y agregarla al valor del índice como: df ['col'] = 'str' + df.index.astype (str)
MEdwin

"astype (str)" podría arruinar la codificación si al final está intentando guardar en un archivo.
Raein Hashemi

2
Cuando intento esto, así como cualquier otro enfoque, obtengo un SettingWithCopyWarning. ¿Hay alguna forma de evitarlo?
Madan Ivan

13

Como alternativa, también puede usar un applycombinado con format(o mejor con f-strings) que encuentro un poco más legible si uno, por ejemplo, también quiere agregar un sufijo o manipular el elemento en sí:

df = pd.DataFrame({'col':['a', 0]})

df['col'] = df['col'].apply(lambda x: "{}{}".format('str', x))

que también produce el resultado deseado:

    col
0  stra
1  str0

Si está usando Python 3.6+, también puede usar f-strings:

df['col'] = df['col'].apply(lambda x: f"str{x}")

dando el mismo resultado.

La versión de f-string es casi tan rápida como la solución de @ RomanPekar (python 3.6.4):

df = pd.DataFrame({'col':['a', 0]*200000})

%timeit df['col'].apply(lambda x: f"str{x}")
117 ms ± 451 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit 'str' + df['col'].astype(str)
112 ms ± 1.04 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

El uso format, sin embargo, es de hecho mucho más lento:

%timeit df['col'].apply(lambda x: "{}{}".format('str', x))
185 ms ± 1.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

mismo resultado, pero mucho más lento ;-)
Philipp_Kats

1
@Philipp_Kats: Agregué algunos horarios, ¡gracias por la sugerencia! Parece que las cuerdas de fa son casi tan rápidas; formatde hecho funciona peor. ¿Cómo te comparaste?
Cleb

¡Oh bien! en mi opinión, .applyes siempre tan rápido o más lento que las operaciones vectorizadas "directas"; incluso si no son más lentos, prefiero evitarlos siempre que sea posible.
Philipp_Kats

@Philipp_Kats: Estoy de acuerdo, sin embargo, en este caso particular lo encuentro más legible cuando también agrego un sufijo, hago algo consigo xmismo, etc., pero eso es solo una cuestión de gustos ... :)
Cleb

4

Puede usar pandas.Series.map:

df['col'].map('str{}'.format)

Aplicará la palabra "str" ​​antes de todos sus valores.


3

Si carga su archivo de tabla con dtype=str
o convierte el tipo de columna a cadena df['a'] = df['a'].astype(str)
, puede usar dicho enfoque:

df['a']= 'col' + df['a'].str[:]

Este enfoque permite anteponer, agregar y subconjuntar cadenas de df.
Funciona en Pandas v0.23.4, v0.24.1. No conozco versiones anteriores.


0

Otra solución con .loc:

df = pd.DataFrame({'col': ['a', 0]})
df.loc[df.index, 'col'] = 'string' + df['col'].astype(str)

Esto no es tan rápido como las soluciones anteriores (> 1 ms por ciclo más lento) pero puede ser útil en caso de que necesite un cambio condicional, como:

mask = (df['col'] == 0)
df.loc[mask, 'col'] = 'string' + df['col'].astype(str)

¿Por qué .indexen df[mask].index?
AMC

@AMC porque para .loc necesitas índices del marco de datos. Significa: df [máscara] devuelve un marco de datos que coincide con la condición y df [máscara] .index devuelve índices del marco de datos. Pero es cierto que también puede hacer lo mismo con df.loc [(df ['col'] == 'a'), 'col'] o df.loc [mask, 'col'].
Lukas

1
porque para .loc necesitas índices del marco de datos. Si df.loc[mask]funciona, y lo hace, entonces .indexes superfluo, ¿verdad?
AMC

@AMC exactamente :). Edité la solución. Gracias.
Lukas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.