熊猫-检查列表列中的字符串列是否按行排列

时间:2019-06-30 01:55:05

标签: python pandas list dataframe apply

我有一个数据框,您可以用它来构建:

dflist=[['123',['abc','qw3','123']],
        ['ab12',['3e4r5','12we3','asd23','q2w3']]]
df=pd.DataFrame(dflist,columns=['check','checklist'])

看起来像这样:

  check                    checklist
0   123              [abc, qw3, 123]
1  ab12  [3e4r5, 12we3, asd23, q2w3]

我要检查“检查”列中的项目是否在“检查列表”列中的列表中。所以我希望结果数据框看起来像:

  check                    checklist checkisin
0   123              [abc, qw3, 123]      True
1  ab12  [3e4r5, 12we3, asd23, q2w3]     False

我尝试了几种方法,包括以多种形式使用.isin,包括apply / lambda。和直接。

此:

df['checkisin']=df.check.isin(df.checklist)

产生:

  check                    checklist  checkisin
0   123              [abc, qw3, 123]      False
1  ab12  [3e4r5, 12we3, asd23, q2w3]      False

有两个错误。

尝试一下: df ['checkisin'] = df.apply(lambda x:x.check.isin(x.checklist)) 出现此错误:

AttributeError: ("'Series' object has no attribute 'check'", 'occurred at index check')

尝试一下:

df['checkisin']=df.apply(lambda x:x['check'] in x.checklist)

给出此错误:

KeyError: ('check', 'occurred at index check')

我确定这里缺少一些简单的东西。我知道我可以循环执行此操作,但是由于我拥有的DF很大,因此正在寻找Pandas Dataframe列明智的解决方案,并试图“最”有效地处理。

谢谢!

4 个答案:

答案 0 :(得分:5)

您有一列列表,当然,pandas没有任何本机支持对结构如此糟糕的数据进行操作的功能。如果您想获得最高的性能,我建议您理解列表:

df['checkisin'] = [c in l for c, l in zip(df['check'], df['checklist'])]
df
  check                    checklist  checkisin
0   123              [abc, qw3, 123]       True
1  ab12  [3e4r5, 12we3, asd23, q2w3]      False

如果您担心NaN和类型不匹配,则可以考虑实施try-except错误处理:

def check_isin(check, checklist):
    try:
        return check in checklist
    except TypeError:
        return np.NaN

df['checkisin'] = [
    check_isin(c, l) for c, l in zip(df['check'], df['checklist'])
]

Evidence suggests列表推导是无法向量化操作的最理想选择。

PS,如果您打算进行大量成员资格测试,请考虑将列表列转换为集合列。


下面是如何对操作进行矢量化的示例。

from itertools import chain

cl = df.pop('checklist')
df = (pd.DataFrame(df.reset_index().values.repeat(cl.str.len(), axis=0), 
                   columns=['group', *df.columns])
        .assign(checklist=list(chain.from_iterable(cl))))

df

   group check checklist
0      0   123       abc
1      0   123       qw3
2      0   123       123
3      1  ab12     3e4r5
4      1  ab12     12we3
5      1  ab12     asd23
6      1  ab12      q2w3
7      1  ab12       123

(df['check'] == df['checklist']).groupby(df.group).any()

group
0     True
1    False
dtype: bool

答案 1 :(得分:4)

我将isinSeries一起使用,isin与Series将首先匹配index,这与list

pd.DataFrame(df.checklist.tolist(),index=df.index).isin(df.check).any(1)
Out[496]: 
0     True
1    False
dtype: bool

pd.DataFrame(df.checklist.tolist(),index=df.index).eq(df.check,0).any(1)

答案 2 :(得分:4)

map

df.assign(checkisin=[*map(lambda s, x: s in x, *map(df.get, df))])

  check                    checklist  checkisin
0   123              [abc, qw3, 123]       True
1  ab12  [3e4r5, 12we3, asd23, q2w3]      False

如果您的数据框具有更多列,则可以更明确

cols = ['check', 'checklist']
df.assign(checkisin=[*map(lambda s, x: s in x, *map(df.get, cols))])

答案 3 :(得分:1)

您可以尝试:

df['checkisin'] = [v in df.checklist[i] for i, v in enumerate(df.check)]

或:

df['checkisin'] = [i in j for i, j in zip(df.check, df.checklist)]

或:

df['checkisin'] = list(map(lambda i, j: i in j, df.check, df.checklist))

或(如果您更喜欢df.assign):

df.assign(checkisin=[*map(lambda i, j: i in j, df.check, df.checklist)])

结果:

  check                    checklist  checkisin
0   123              [abc, qw3, 123]       True
1  ab12  [3e4r5, 12we3, asd23, q2w3]      False