Dataframe 列中列表值的Pandas过滤器列表

wko9yo5t  于 2023-01-19  发布在  其他
关注(0)|答案(3)|浏览(255)

我有一个 Dataframe 如下

sample_df = pd.DataFrame({'single_proj_name': [['jsfk'],['fhjk'],['ERRW'],['SJBAK']],
                              'single_item_list': [['ABC_123'],['DEF123'],['FAS324'],['HSJD123']],
                              'single_id':[[1234],[5678],[91011],[121314]],
                              'multi_proj_name':[['AAA','VVVV','SASD'],['QEWWQ','SFA','JKKK','fhjk'],['ERRW','TTTT'],['SJBAK','YYYY']],
                              'multi_item_list':[[['XYZAV','ADS23','ABC_123'],['ABC_123','ADC_123']],['XYZAV','DEF123','ABC_123','SAJKF'],['QWER12','FAS324'],['JFAJKA','HSJD123']],
                              'multi_id':[[[2167,2147,29481],[5432,1234]],[2313,57567,2321,7898],[1123,8775],[5237,43512]]})

我想做以下几点
a)从single_item_list中为每行选取值
B)在同一行的multi_item_list列中搜索该值。请注意,某些行的值可能是list of lists
c)如果发现匹配,则仅保留multi_item_list中的匹配值,并从multi_item_list中删除所有其他不匹配值
d)根据匹配项的位置,在multi_id列表中查找对应的值,只保留该项,从列表中删除所有其他位置项
所以,我尝试了下面的方法,但是它对嵌套列表不起作用

for a, b, c in zip(sample_df['single_item_list'],sample_df['multi_item_list'],sample_df['multi_id']):
    for i, x in enumerate(b):
        print(x)
        print(a[0])
        if a[0] in x:
            print(x.index(a[0]))
            pos = x.index(a[0])
            print(c[pos-1])

我希望我的输出如下。在真实的世界中,我会有更多的情况下,如第一输入行(嵌套列表与多个层次)

slwdgvem

slwdgvem1#

下面是一种处理任意数量嵌套列表的方法:

def func(z, X, Y):
    A, B = [], []
    for x, y in zip(X, Y):
        if isinstance(x, list):
            a, b = func(z, x, y)
            A.append(a), B.append(b)

        if x == z:
            A.append(x), B.append(y)
    return A, B

c = ['single_item_list', 'multi_item_list', 'multi_id']
df[c[1:]] = [func(z, X, Y) for [z], X, Y in df[c].to_numpy()]

结果

single_proj_name single_item_list single_id           multi_proj_name         multi_item_list           multi_id
0           [jsfk]        [ABC_123]    [1234]         [AAA, VVVV, SASD]  [[ABC_123], [ABC_123]]  [[29481], [5432]]
1           [fhjk]         [DEF123]    [5678]  [QEWWQ, SFA, JKKK, fhjk]                [DEF123]            [57567]
2           [ERRW]         [FAS324]   [91011]              [ERRW, TTTT]                [FAS324]             [8775]
3          [SJBAK]        [HSJD123]  [121314]             [SJBAK, YYYY]               [HSJD123]            [43512]
eufgjt7s

eufgjt7s2#

您提供的代码使用zip()函数同时迭代DataFrame的“single_item_list”、“multi_item_list”和“multi_id”列。
对于每次迭代,它使用嵌套的for循环来迭代“multi_item_list”列中的子列表。它使用in运算符检查“single_item_list”的第一个元素是否存在于当前子列表中。如果存在,它使用索引查找子列表中匹配元素的索引()方法,并将其赋给变量pos,然后在'multi_id'列的相应索引中打印该值。
这段代码可以正常工作,但它只会打印multi_id列中的匹配值,而不会更新数据框的multi_item_list和multi_id列。为了用匹配值更新数据框,您必须使用.iloc方法来更新数据框。例如:样本_df.iloc[i,j] =新瓦尔

for i, (single, multi_item, multi_id) in enumerate(zip(sample_df['single_item_list'],sample_df['multi_item_list'],sample_df['multi_id'])):
for j, item_list in enumerate(multi_item):
    if single[0] in item_list:
        pos = item_list.index(single[0])
        sample_df.at[i,'multi_item_list'] = [item_list]
        sample_df.at[i,'multi_id'] = [multi_id[j]]

打印(样本df)
这将使用“multi_item_list”和“multi_id”列中的筛选值打印更新的DataFrame。请注意,print(sample_df)应放在for循环之后,以确保在更新后打印表。
此代码同时迭代DataFrame的“single_item_list”、“multi_item_list”和“multi_id”列。在每次迭代中,它使用嵌套的for循环迭代“multi_item_list”列中的子列表。它使用in运算符检查“single_item_list”的第一个元素是否存在于当前子列表中。如果存在,它使用index()方法在子列表中查找匹配元素的索引,并将其赋给变量pos。然后,它使用at方法用匹配的值更新DataFrame中当前索引处的'multi_item_list'和'multi_id'列。
请注意,此代码将从“multi_item_list”和“multi_id”列中删除不匹配的项目,如果没有匹配的项目,它将保留原始值。

yhxst69z

yhxst69z3#

我使用isinstance来检查它是否是一个嵌套列表,并得出了如下所示的结果,这是预期的输出。

for i, (single, multi_item, multi_id) in enumerate(zip(sample_df['single_item_list'],sample_df['multi_item_list'],sample_df['multi_id'])):
    if (any(isinstance(i, list) for i in multi_item)) == False:
        for j, item_list in enumerate(multi_item):
            if single[0] in item_list:
                pos = item_list.index(single[0])
                sample_df.at[i,'multi_item_list'] = [item_list]
                sample_df.at[i,'multi_id'] = [multi_id[j]]
    else:
        print("under nested list")
        for j, item_list in enumerate(zip(multi_item,multi_id)):
            if single[0] in multi_item[j]:
                pos = multi_item[j].index(single[0])
                sample_df.at[i,'multi_item_list'][j] = single[0]
                sample_df.at[i,'multi_id'][j] = multi_id[j][pos]
            else:
                sample_df.at[i,'multi_item_list'][j] = np.nan
                sample_df.at[i,'multi_id'][j] = np.nan

相关问题