Pandas überschreiben Werte in mehreren Spalten gleichzeitig, basierend auf der Bedingung der Werte in einer Spalte

11

Ich habe einen solchen 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']})

Ich möchte die Länge der Liste nach dem Teilen auf ":" in Spalte 1 erhalten, dann möchte ich die Werte überschreiben, wenn die Länge> 2 ist, oder die Werte nicht überschreiben, wenn die Länge <= 2 ist.

Idealerweise so schnell wie möglich in einer Zeile.

Derzeit versuche ich, aber es gibt ValueError zurück.

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

EDIT: Bedingung auf Spalte 1. EDIT2: Danke für all die tollen und schnell gegebenen Antworten. tolle! EDIT3: Timing in 10 ^ 6 Zeilen:

@ansev 3.2657s

@jezrael 0.8922s

@ anky_91 1.9511s

dkrynicki
quelle
Ist die Bedingung an col2oder col1?
anishtain4
Ich entschuldige mich für den Fehler. Es ist col1.
dkrynicki

Antworten:

8

Verwenden Series.str.count, Hinzufügen 1, Vergleichen Series.gtund Zuweisen einer Liste zu gefilterten Spalten in der Liste:

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
quelle
2
Dies ist die beste Antwort, da keine temporäre Aufteilung gespeichert wird. Warum jedoch nicht verwenden, gt(1)anstatt 1 und hinzuzufügen gt(2)?
anishtain4
@ anishtain4 - yop, stimme zu
jezrael
10

Sie müssen series.str.len()nach dem Aufteilen die Länge der Liste bestimmen, dann können Sie die Liste vergleichen und verwenden .loc[], wo immer die Bedingung übereinstimmt:

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

Ein anderer Ansatz ist Series.str.splitmit expand = Trueund DataFrame.countmit 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
quelle