Pandas 如何从数据框和列中的列表中弹出行

Pandas 如何从数据框和列中的列表中弹出行,pandas,list,dataframe,Pandas,List,Dataframe,我有一个数据框,其中一列是列表。该列表是标签的通用列表 df = pd.DataFrame({'label': ['cell_1', 'cell_1', 'cell_1', 'cell_1', 'cell_2', 'cell_2', 'cell_2'], 'index': [1, 2, 5, 6, 1, 18, 5], 'item': [121, 989, 222, 333, 878, 777, 878],

我有一个数据框,其中一列是列表。该列表是标签的通用列表

    df = pd.DataFrame({'label': ['cell_1', 'cell_1', 'cell_1', 'cell_1', 'cell_2', 'cell_2', 'cell_2'],
                   'index': [1, 2, 5, 6, 1, 18, 5],
                   'item': [121, 989, 222, 333, 878, 777, 878],
                   'list': [[121, 454, 989], [121, 454, 989], [121, 454, 989], [121, 454, 989], [111, 777, 999], [111, 777, 999], [111, 777, 999]]})

    label    index  item    list
0   cell_1   1      121     [121, 454, 989]
1   cell_1   2      989     [121, 454, 989]
2   cell_1   5      222     [121, 454, 989]
3   cell_1   6      333     [121, 454, 989]
4   cell_2   1      878     [111, 777, 999]
5   cell_2   18     777     [111, 777, 999]
6   cell_2   5      878     [111, 777, 999]
我想检查item列中的值是否在列表中。如果是,我想将行弹出到它自己的数据帧中:

popped_df

   label    index   item
0  cell_1   1       121
1  cell_1   2       989
2  cell_2   18      777
df
   label    index   item    list
0  cell_1   5       222     [454]
1  cell_1   6       333     [454]
2  cell_2   1       878     [111, 999]
3  cell_2   5       878     [111, 999]
并从剩余数据框的列表中删除项值:

popped_df

   label    index   item
0  cell_1   1       121
1  cell_1   2       989
2  cell_2   18      777
df
   label    index   item    list
0  cell_1   5       222     [454]
1  cell_1   6       333     [454]
2  cell_2   1       878     [111, 999]
3  cell_2   5       878     [111, 999]
我尝试了很多东西,但都遇到了大问题。我认为解决方案可能是将数据放在嵌套字典中,以label作为键,每个索引作为一个值并进行迭代。我宁愿不要从数据帧到字典再到字典,即使这意味着性能很慢

提前谢谢你

如果希望将列表保存在列表中而不是分解数据帧,则可以使用列表理解来执行此操作。由于要比较多个列,请在数据帧上使用.applylambda x:,其中x是数据帧,并传递列和轴=1,以在默认轴=0上按列移动。使用explode时性能可能会更好,但我将测试此方法与explode方法的比较。 要去除初始数据帧的值,请使用非常类似的列表理解技术
我建议您分解列表,然后执行基本布尔索引器:

df.分解“列表” .loc[lambda df:~df['list'].isindf['item']&~df['item'].isindf['list']] .pivot_tableindex=['label'、'index'、'item'],values='list',aggfunc=list .reset_索引 这给了我:

    label  index  item        list
0  cell_1      5   222       [454]
1  cell_1      6   333       [454]
2  cell_2      1   878  [111, 999]
3  cell_2      5   878  [111, 999]
但我建议您不要将值放在列表中,忽略对pivot_表的调用

您可以翻转逻辑以获取其他数据帧:

popped_df

   label    index   item
0  cell_1   1       121
1  cell_1   2       989
2  cell_2   18      777
df
   label    index   item    list
0  cell_1   5       222     [454]
1  cell_1   6       333     [454]
2  cell_2   1       878     [111, 999]
3  cell_2   5       878     [111, 999]
df.分解“列表” .loc[lambda df:df['list'].isindf['item']&df['item'].isindf['list']] .dropcolumns=['list'] .drop_duplicateSubset=['label','index'] .to_字符串 即:

    label  index  item
0  cell_1      1   121
1  cell_1      2   989
5  cell_2     18   777
请注意,一般来说,所谓的整洁数据更容易处理:

df.explode'list'.reset\u indexdrop=True
Paul和David的答案非常有用,但不幸的是,当我将它们应用于我的完整数据集时,我发现他们的解决方案从整个列表列中删除了项,而不仅仅是标签的公共列表。例如,如果我添加的列表项同时出现在单元格_1和单元格_2列表中:

df = pd.DataFrame({'label': ['cell_1', 'cell_1', 'cell_1', 'cell_1', 'cell_2', 'cell_2', 'cell_2'],
               'index': [1, 2, 5, 6, 1, 18, 5],
               'item': [121, 989, 222, 333, 878, 777, 878],
               'list': [[121, 454, 989], [121, 454, 989], [121, 454, 989], [121, 454, 989], [121, 777, 999], [121, 777, 999], [121, 777, 999]]})

label   index   item    list
0   cell_1  1   121 [121, 454, 989]
1   cell_1  2   989 [121, 454, 989]
2   cell_1  5   222 [121, 454, 989]
3   cell_1  6   333 [121, 454, 989]
4   cell_2  1   878 [121, 777, 999]
5   cell_2  18  777 [121, 777, 999]
6   cell_2  5   878 [121, 777, 999]
对于这两种解决方案,单元格_2的列表已被删除,尽管我只想将其从单元格_1共有的列表单元格中删除:

s = df.apply(lambda x: any([True for y in x['list'] if x['item'] == y ]), axis=1)
df1 = df[s].drop('list', axis=1)
df['list'] = df.apply(lambda x: [y for y in x['list'] if y not in df1['item'].unique()], axis=1)
df = df[~s]
df1, df
(    label  index  item
 0  cell_1      1   121
 1  cell_1      2   989
 5  cell_2     18   777,
     label  index  item   list
 2  cell_1      5   222  [454]
 3  cell_1      6   333  [454]
 4  cell_2      1   878  [999]
 6  cell_2      5   878  [999])
我最后做的是爆炸数据,使其整洁:

df.explode('list').reset_index(drop=True)
df
            label   index   item    list
0   cell_1  1       121     121
1   cell_1  1       121     454
2   cell_1  1       121     989
3   cell_1  2       989     121
4   cell_1  2       989     454
5   cell_1  2       989     989
6   cell_1  5       222     121
7   cell_1  5       222     454
8   cell_1  5       222     989
9   cell_1  6       333     121
10  cell_1  6       333     454
11  cell_1  6       333     989
12  cell_2  1       878     121
13  cell_2  1       878     777
14  cell_2  1       878     999
15  cell_2  18      777     121
16  cell_2  18      777     777
17  cell_2  18      777     999
18  cell_2  5       878     121
19  cell_2  5       878     777
20  cell_2  5       878     999
然后添加额外的列:

df['lookup1'] = df['label'] + "-" + df['item'].astype(str)
df.loc[(df['item'] == df['list']), 'lookup2'] = df['label'] + "-" + df['item'].astype(str)
df["selector"] = df['lookup1'].isin(df["lookup2"])

df

    label   index   item    list    lookup1      lookup2    selector
0   cell_1  1       121     121     cell_1-121  cell_1-121  True
1   cell_1  1       121     454     cell_1-121  NaN         True
2   cell_1  1       121     989     cell_1-121  NaN         True
3   cell_1  2       989     121     cell_1-989  NaN         True
4   cell_1  2       989     454     cell_1-989  NaN         True
5   cell_1  2       989     989     cell_1-989  cell_1-989  True
6   cell_1  5       222     121     cell_1-222  NaN         False
7   cell_1  5       222     454     cell_1-222  NaN         False
8   cell_1  5       222     989     cell_1-222  NaN         False
9   cell_1  6       333     121     cell_1-333  NaN         False
10  cell_1  6       333     454     cell_1-333  NaN         False
11  cell_1  6       333     989     cell_1-333  NaN         False
12  cell_2  1       878     121     cell_2-878  NaN         False
13  cell_2  1       878     777     cell_2-878  NaN         False
14  cell_2  1       878     999     cell_2-878  NaN         False
15  cell_2  18      777     121     cell_2-777  NaN         True
16  cell_2  18      777     777     cell_2-777  cell_2-777  True
17  cell_2  18      777     999     cell_2-777  NaN         True
18  cell_2  5       878     121     cell_2-878  NaN         False
19  cell_2  5       878     777     cell_2-878  NaN         False
20  cell_2  5       878     999     cell_2-878  NaN         False

在这一点上,我可以对选择器列进行操作。当然有更优雅的方法可以做到这一点吗?

是否需要保留列表?这类事情可能会更简单,而且性能更好,因为列表的值都在它们自己的列中。不必保留在列表中,它位于列表中的优点是列表的长度是可变的。第一次,我对列表数据做了一个数据透视图,其中包含了列表0、列表1、列表2等列,我将这些列合并到了数据透视图中。我看到了如何使用一组公式,比如:df.loc[df['item']==df['list\u item0'],'in\u list'=df['item']df.loc[df['item']==df['list\u item1'],'in\u list'=df['item'],这是我将使用的。
df['lookup1'] = df['label'] + "-" + df['item'].astype(str)
df.loc[(df['item'] == df['list']), 'lookup2'] = df['label'] + "-" + df['item'].astype(str)
df["selector"] = df['lookup1'].isin(df["lookup2"])

df

    label   index   item    list    lookup1      lookup2    selector
0   cell_1  1       121     121     cell_1-121  cell_1-121  True
1   cell_1  1       121     454     cell_1-121  NaN         True
2   cell_1  1       121     989     cell_1-121  NaN         True
3   cell_1  2       989     121     cell_1-989  NaN         True
4   cell_1  2       989     454     cell_1-989  NaN         True
5   cell_1  2       989     989     cell_1-989  cell_1-989  True
6   cell_1  5       222     121     cell_1-222  NaN         False
7   cell_1  5       222     454     cell_1-222  NaN         False
8   cell_1  5       222     989     cell_1-222  NaN         False
9   cell_1  6       333     121     cell_1-333  NaN         False
10  cell_1  6       333     454     cell_1-333  NaN         False
11  cell_1  6       333     989     cell_1-333  NaN         False
12  cell_2  1       878     121     cell_2-878  NaN         False
13  cell_2  1       878     777     cell_2-878  NaN         False
14  cell_2  1       878     999     cell_2-878  NaN         False
15  cell_2  18      777     121     cell_2-777  NaN         True
16  cell_2  18      777     777     cell_2-777  cell_2-777  True
17  cell_2  18      777     999     cell_2-777  NaN         True
18  cell_2  5       878     121     cell_2-878  NaN         False
19  cell_2  5       878     777     cell_2-878  NaN         False
20  cell_2  5       878     999     cell_2-878  NaN         False