python pandas

python - Cortar la columna Dataframe en función de la longitud de las cadenas



pandas (6)

Me gustaría eliminar los primeros 3 caracteres de las cadenas en una columna de Dataframe donde la longitud de la cadena es> 4

Si no, deberían seguir siendo los mismos.

P.ej

bloomberg_ticker_y AIM9 DJEM9 # (should be M9) FAM9 IXPM9 # (should be M9)

Puedo filtrar las cuerdas por longitud:

merged[''bloomberg_ticker_y''].str.len() > 4

y cortar las cuerdas:

merged[''bloomberg_ticker_y''].str[-2:]

Pero no estoy seguro de cómo poner esto junto y aplicarlo a mi marco de datos

Cualquier ayuda sería apreciada.


Otro enfoque es usar expresiones regulares:

df["bloomberg_ticker_y"].str.replace(r".{3,}(?=.{2}$)", "") #0 AIM9 #1 M9 #2 FAM9 #3 M9

El patrón significa:

  • .{3,} : combina 3 o más caracteres
  • (?=.{2}$) : anticipación positiva de exactamente 2 caracteres seguidos del final de la cadena.

Puede usar numpy.where para aplicar una condición para seleccionar segmentos en función de la longitud de la cadena.

np.where(df[''bloomberg_ticker_y''].str.len() > 4, df[''bloomberg_ticker_y''].str[3:], df[''bloomberg_ticker_y'']) # array([''AIM9'', ''M9'', ''FAM9'', ''M9''], dtype=object)

df[''bloomberg_ticker_sliced''] = ( np.where(df[''bloomberg_ticker_y''].str.len() > 4, df[''bloomberg_ticker_y''].str[3:], df[''bloomberg_ticker_y''])) df bloomberg_ticker_y bloomberg_ticker_sliced 0 AIM9 AIM9 1 DJEM9 M9 2 FAM9 FAM9 3 IXPM9 M9

Si te apetece una solución basada en un map vectorizado, es

df[''bloomberg_ticker_y''].map(lambda x: x[3:] if len(x) > 4 else x) 0 AIM9 1 M9 2 FAM9 3 M9 Name: bloomberg_ticker_y, dtype: object


Puede utilizar una lista de comprensión:

df = pd.DataFrame({''bloomberg_ticker_y'' : [''AIM9'', ''DJEM9'', ''FAM9'', ''IXPM9'']}) df[''new''] = [x[-2:] if len(x)>4 else x for x in df[''bloomberg_ticker_y'']]

Salida:

bloomberg_ticker_y new 0 AIM9 AIM9 1 DJEM9 M9 2 FAM9 FAM9 3 IXPM9 M9


Puedes usar DataFrame.mask :

df[''bloomberg_ticker_y''] = (df.bloomberg_ticker_y.mask( df.bloomberg_ticker_y.str.len().gt(4), other=df.bloomberg_ticker_y.str[-2:])) bloomberg_ticker_y 0 AIM9 1 M9 2 FAM9 3 M9


También puede utilizar DataFrame.apply :

import pandas as pd df = pd.DataFrame({''bloomberg_ticker_y'' : [''AIM9'', ''DJEM9'', ''FAM9'', ''IXPM9'']}) df[''bloomberg_ticker_y''] = df.apply(lambda x: (x[''bloomberg_ticker_y''][3:] if len(x[''bloomberg_ticker_y'']) > 4 else x[''bloomberg_ticker_y'']) , axis=1)

Salida:

bloomberg_ticker_y 0 AIM9 1 M9 2 FAM9 3 M9


Vio una gran variedad de respuestas, así que decidí compararlas en términos de velocidad:

# Create big size test dataframe df = pd.DataFrame({''bloomberg_ticker_y'' : [''AIM9'', ''DJEM9'', ''FAM9'', ''IXPM9'']}) df = pd.concat([df]*100000) df.shape #Out (400000, 1)

CS95 # 1 np.where

%%timeit np.where(df[''bloomberg_ticker_y''].str.len() > 4, df[''bloomberg_ticker_y''].str[3:], df[''bloomberg_ticker_y''])

Resultado:

163 ms ± 12.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

CS95 # 2 solución basada en map vectorizados

%%timeit df[''bloomberg_ticker_y''].map(lambda x: x[3:] if len(x) > 4 else x)

Resultado:

86 ms ± 7.31 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Yatu DataFrame.mask

%%timeit df.bloomberg_ticker_y.mask(df.bloomberg_ticker_y.str.len().gt(4), other=df.bloomberg_ticker_y.str[-2:])

Resultado:

187 ms ± 18.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Vlemaistre list comprehension

%%timeit [x[-2:] if len(x)>4 else x for x in df[''bloomberg_ticker_y'']]

Resultado:

84.8 ms ± 4.85 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

pault str.replace con regex

%%timeit df["bloomberg_ticker_y"].str.replace(r".{3,}(?=.{2}$)", "")

Resultado:

324 ms ± 17.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Cobra DataFrame.apply

%%timeit df.apply(lambda x: (x[''bloomberg_ticker_y''][3:] if len(x[''bloomberg_ticker_y'']) > 4 else x[''bloomberg_ticker_y'']) , axis=1)

Resultado:

6.83 s ± 387 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Conclusión

  • El método más rápido es la list comprehension seguida de cerca por una solución basada en map vectorizados.

  • El método más lento es DataFrame.apply con diferencia (como se esperaba) seguido de str.replace con regex