los pandas sobrescriben valores en varias columnas a la vez según la condición de los valores en una columna

11

Tengo ese DataFrame:

df = pd.DataFrame(data={
    'col0': [11, 22,1, 5]
    'col1': ['aa:a:aaa', 'a:a', 'a', 'a:aa:a:aaa'],
    'col2': ["foo", "foo", "foobar", "bar"],
    'col3': [True, False, True, False],
    'col4': ['elo', 'foo', 'bar', 'dupa']})

Quiero obtener la longitud de la lista después de dividir en ":" en col1, luego quiero sobrescribir los valores si length> 2 O no sobrescribir los valores si length <= 2.

Idealmente, en una línea lo más rápido posible.

Actualmente, lo intento pero devuelve ValueError.

df[['col1', 'col2', 'col3']] = df.loc[df['col1'].str.split(":").apply(len) > 2], ("", "", False), df[['col1', 'col2', 'col3']])

EDITAR: condición en col1. EDIT2: gracias por todas las excelentes y rápidas respuestas. ¡asombroso! EDITAR3: sincronización en 10 ^ 6 filas:

@ansev 3.2657s

@jezrael 0.8922s

@ anky_91 1.9511s

dkrynicki
fuente
¿La condición está en col2o col1?
anishtain4
Me disculpo por el error. Es col1.
dkrynicki

Respuestas:

8

Use Series.str.count, agregue 1, compare Series.gty asigne listas a columnas filtradas en la lista:

df.loc[df['col1'].str.count(":").add(1).gt(2), ['col1','col2','col3']] = ["", "", False]
print (df)
   col0 col1    col2   col3  col4
0    11               False   elo
1    22  a:a     foo  False   foo
2     1    a  foobar   True   bar
3     5               False  dupa
jezrael
fuente
2
Esta es la mejor respuesta, ya que no almacena una división temporal, pero ¿por qué no usar en gt(1)lugar de agregar 1 y gt(2)?
anishtain4
@ anishtain4 - sí, de acuerdo
jezrael
10

series.str.len()Después de dividir, necesita determinar la longitud de la lista, luego puede comparar y usar .loc[], asignar la lista donde coincida la condición:

df.loc[df['col1'].str.split(":").str.len()>2,['col1','col2','col3']]=["", "", False]
print(df)

   col0 col1    col2   col3  col4
0    11               False   elo
1    22  a:a     foo  False   foo
2     1    a  foobar   True   bar
3     5               False  dupa
anky
fuente
5

Otro enfoque es Series.str.splitcon expand = Truey DataFrame.countcon axis=1.

df.loc[df['col1'].str.split(":",expand = True).count(axis=1).gt(2),['col1','col2','col3']]=["", "", False]
print(df)
   col0 col1    col2   col3  col4
0    11               False   elo
1    22  a:a     foo  False   foo
2     1    a  foobar   True   bar
3     5               False  dupa
ansev
fuente