os pandas sobrescrevem valores em várias colunas de uma só vez com base na condição de valores em uma coluna

11

Eu tenho esse 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']})

Desejo obter o comprimento da lista após a divisão em ":" em col1, então desejo sobrescrever os valores se comprimento> 2 OU não sobrescrever os valores se comprimento <= 2.

Idealmente, em uma linha o mais rápido possível.

Atualmente, eu tento, mas ele retorna ValueError.

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

EDIT: condição em col1. EDIT2: obrigado por todas as ótimas e rapidamente fornecidas respostas. surpreendente! EDIT3: tempo em 10 ^ 6 linhas:

@ansev 3.2657s

@jezrael 0.8922s

@ anky_91 1.9511s

dkrynicki
fonte
A condição está ativada col2ou col1?
anishtain4
Peço desculpas pelo erro. É col1.
dkrynicki 20/01

Respostas:

8

Use Series.str.count, adicione 1, compare Series.gte atribua a lista a colunas filtradas na 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
fonte
2
Essa é a melhor resposta, pois não armazena uma divisão temporária, mas por que não usar em gt(1)vez de adicionar 1 e gt(2)?
anishtain4 20/01
@ anishtain4 - yop, concorda
jezrael 20/01
10

series.str.len()Depois de dividir, é necessário determinar o comprimento da lista e comparar e .loc[], atribuir a lista sempre que a condição corresponder:

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
fonte
5

Outra abordagem é Series.str.splitcom expand = Truee DataFrame.countcom 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
fonte