pandy zastępują wartości w wielu kolumnach jednocześnie, w zależności od warunków wartości w jednej kolumnie

11

Mam takie 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']})

Chcę uzyskać długość listy po podzieleniu na „:” w kolumnie 1, a następnie chcę zastąpić wartości, jeśli długość> 2 LUB nie nadpisywać wartości, jeśli długość <= 2.

Najlepiej w jednej linii tak szybko, jak to możliwe.

Obecnie próbuję, ale zwraca ValueError.

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

EDYCJA: warunek na kolumnie 1. EDYCJA 2: dziękuję za wszystkie wspaniałe i szybko udzielone odpowiedzi. niesamowity! EDIT3: czas na 10 ^ 6 wierszy:

@ansev 3.2657s

@jezrael 0,8922s

@ anky_91 1.9511s

dkrynicki
źródło
Czy stan jest włączony col2czy col1?
anishtain4
Przepraszam za błąd. To jest col1.
dkrynicki

Odpowiedzi:

8

Użyj Series.str.count, dodaj 1, porównaj Series.gti przypisz listę do filtrowanych kolumn na liście:

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
źródło
2
To najlepsza odpowiedź, ponieważ nie przechowuje tymczasowego podziału, ale dlaczego nie użyć gt(1)zamiast dodania 1 i gt(2)?
anishtain4
@ anishtain4 - yop, zgadzam się
jezrael
10

series.str.len()Po podzieleniu musisz określić długość listy, a następnie możesz porównać i .loc[]przydzielić, przypisać listę tam, gdzie spełniony jest warunek:

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
źródło
5

Inne podejście jest Series.str.splitz expand = Truei DataFrame.countz 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
źródło