基于列子集的pandas行选择

时间:2017-05-25 21:31:47

标签: python pandas

我有一个包含4列的Pandas数据框 - 如下所示:

          A                       B            C           D
2         c  {4889, 9978, 1230, 4921}        {30}         4
4         m  {4889, 9978, 1230, 4921}        {30}         4
0         a        {4889, 1230, 4921}        {30}         3
7         q              {1240, 4921}        {30}         2
9         x              {9978, 1230}        {30}         2

另外,我有一个这样的列表:

[[1230,4889],[1240, 4921]]

我想从数据框中选择那些列B值是任何列表项的超集的行。对于给定的示例,输出将是:

          A                       B            C           D
2         c  {4889, 9978, 1230, 4921}        {30}         4
4         m  {4889, 9978, 1230, 4921}        {30}         4
0         a        {4889, 1230, 4921}        {30}         3
7         q              {1240, 4921}        {30}         2

任何好方法吗?它并不像做以下事情一样直接:

df.loc[df['B'] == 'xyz']

2 个答案:

答案 0 :(得分:2)

通过设置操作使用numpy广播。 注意:>= for sets返回正确值,右侧是左侧的子集。相等部分允许相等的集合。

s = np.array([set(l) for l in [[1230, 4889], [1240, 4921]]])

m = (df['B'].values >= s[:, None]).any(0)

df[m]

   A                         B     C  D
2  c  {4889, 9978, 1230, 4921}  {30}  4
4  m  {4889, 9978, 1230, 4921}  {30}  4
0  a        {4889, 1230, 4921}  {30}  3
7  q              {1240, 4921}  {30}  2

答案 1 :(得分:0)

一种天真的方法,只需检查列表中每个元素的包含。

import pandas as pd
from io import StringIO

df = pd.read_csv(StringIO("""          A                       B            C           D
    2         c  {4889, 9978, 1230, 4921}        {30}         4
    4         m  {4889, 9978, 1230, 4921}        {30}         4
    0         a        {4889, 1230, 4921}        {30}         3
    7         q              {1240, 4921}        {30}         2
    9         x              {9978, 1230}        {30}         2""",
    ), sep=r'  +')

df['B'] = df.B.apply(eval)

lst = [[1230,4889],[1240, 4921]]
lst_sets = [set(l) for l in lst]

df_res = df[df.B.apply(lambda s: any(not(s2 - s) for s2 in lst_sets))]