panda menimpa nilai dalam beberapa kolom sekaligus berdasarkan kondisi nilai dalam satu kolom

11

Saya memiliki DataFrame tersebut:

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

Saya ingin mendapatkan panjang daftar setelah dipisah pada ":" di col1, maka saya ingin menimpa nilai jika panjang> 2 ATAU tidak menimpa nilai jika panjang <= 2.

Idealnya, dalam satu baris secepat mungkin.

Saat ini, saya mencoba tetapi mengembalikan ValueError.

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

EDIT: kondisi pada col1. EDIT2: terima kasih atas semua jawaban yang bagus dan cepat diberikan. luar biasa! EDIT3: waktu pada 10 ^ 6 baris:

@ansev 3.2657s

@jezrael 0.8922s

@ anky_91 1.9511s

dkrynicki
sumber
Apakah kondisinya menyala col2atau col1?
anishtain4
Saya minta maaf atas kesalahan ini. Itu col1.
dkrynicki

Jawaban:

8

Gunakan Series.str.count, tambahkan 1, bandingkan dengan, Series.gtdan tetapkan daftar ke kolom yang difilter dalam daftar:

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
sumber
2
Ini adalah jawaban terbaik karena tidak menyimpan pemisahan sementara, tetapi mengapa tidak menggunakan gt(1)alih-alih menambahkan 1 dan gt(2)?
anishtain4
@ anishtain4 - yop, setuju
jezrael
10

Anda perlu series.str.len()setelah memisahkan untuk menentukan panjang daftar, kemudian Anda dapat membandingkan dan menggunakan .loc[], menetapkan daftar di mana pun kondisi cocok:

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

Pendekatan lain adalah Series.str.splitdengan expand = Truedan DataFrame.countdengan 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
sumber