熊猫根据一列中的值条件一次覆盖多列中的值


11

我有这样的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']})

我想在col1中的“:”上分割后得到列表的长度,然后如果长度> 2则覆盖值,或者如果长度<= 2则不覆盖值。

理想情况下,尽可能快地排成一行。

目前,我尝试但它返回ValueError。

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

编辑:col1条件。EDIT2:感谢您提供的所有出色的快速答复。惊人!EDIT3:在10 ^ 6行上计时:

@ansev 3.2657s

@jezrael 0.8922s

@ anky_91 1.9511秒


条件是col2还是col1
anishtain4

我为这个错误表示歉意。是col1。
dkrynicki

Answers:


8

使用Series.str.count,添加1,比较依据Series.gt并将列表分配给列表中的过滤列:

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

2
这是最好的答案,因为它不存储临时拆分,但是为什么不使用gt(1)而不是将1和相加gt(2)呢?
anishtain4

@ anishtain4-是的,同意
jezrael

10

series.str.len()拆分后需要确定列表的长度,然后可以比较和使用.loc[],在条件匹配的地方分配列表:

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

5

另一种方法是Series.str.splitexpand = TrueDataFrame.countaxis=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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.