在包含项列表的列中查找公共值

2024-09-27 19:27:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数据集,其中包含一些列,这些列是一个项目列表。下面我举了一个例子。我正在尝试查找列表中有100%匹配项的条目。我想找90%或更低的。你知道吗

>>> df2 = pd.DataFrame({ 'ID':['1', '2', '3', '4', '5', '6', '7', '8'], 'Productdetailed': [['Phone', 'Watch', 'Pen'], ['Pencil', 'fork', 'Eraser'], ['Apple', 'Mango', 'Orange'], ['Something', 'Nothing', 'Everything'], ['Eraser', 'fork', 'Pencil'], ['Phone', 'Watch', 'Pen'],['Apple', 'Mango'], ['Pen', 'Phone', 'Watch']]})

>>> df2
ID                   Productdetailed
0  1               [Phone, Watch, Pen]
1  2            [Pencil, fork, Eraser]
2  3            [Apple, Mango, Orange]
3  4  [Something, Nothing, Everything]
4  5            [Eraser, fork, Pencil]
5  6               [Phone, Watch, Pen]
6  7                    [Apple, Mango]
7  8               [Pen, Phone, Watch]

如果注意到df2中的索引0和索引7,则它们具有相同的项集,但顺序不同。其中索引0和索引5具有相同顺序的相同项。我想把他们两个看作是一对。我试过groupbyseries.isin()。我还尝试将数据集拆分为两个数据集,但由于类型错误而失败。你知道吗

首先,我想计算完全匹配的项的数量(匹配行的数量也可以)以及它匹配到的行索引号。但是当有像df2中的索引2和索引6这样只有部分匹配的项时。我想说的是已经匹配的项目的百分比,以及与之对应的列号。你知道吗

我提到过。我试图将特定列值的数据分为两部分。那么

applied df2['Intersection'] = 
     [list(set(a).intersection(set(b))) 
         for a, b in zip(df2_part1.Productdetailed, df2_part2.Productdetailed)
     ]

,其中ab是来自df2_part1df2_part2的碎片的Productdetailed列。你知道吗

有办法吗?请帮忙


Tags: 数据项目idapple列表phoneforkwatch
2条回答

此解决方案解决了精确匹配任务(代码复杂度非常高,不建议使用):

#First create a dummy column of Productdetailed which is sorted
df2['dummy'] = df2['Productdetailed'].apply(sorted)
#Create Matching column which stores index of first matched list
df2['Matching'] = np.nan

#Code for finding the exact matches and assigning indices in Matching column
for index1,lst1 in enumerate(df2['dummy']):
    for index2,lst2 in enumerate(df2['dummy']):
        if index1<index2:
            if (lst1 == lst2):
                if np.isnan(df2.loc[index2,'Matching']):
                    df2.loc[index1,'Matching'] = index1
                    df2.loc[index2,'Matching'] = index1

#Finding the sum of total exact matches
print(df2['Matching'].notnull().sum())
5

#Deleting the dummy column
del df2['dummy']

#Final Dataframe
print(df2)

  ID                   Productdetailed  Matching
0  1               [Phone, Watch, Pen]       0.0
1  2            [Pencil, fork, Eraser]       1.0
2  3            [Apple, Mango, Orange]       NaN
3  4  [Something, Nothing, Everything]       NaN
4  5            [Eraser, fork, Pencil]       1.0
5  6               [Phone, Watch, Pen]       0.0
6  7                    [Apple, Mango]       NaN
7  8               [Pen, Phone, Watch]       0.0

对于完全匹配和部分匹配使用(如果至少有2个值匹配,则部分匹配也可以更改):

#First create a dummy column of Productdetailed which is sorted
df2['dummy'] = df2['Productdetailed'].apply(sorted)
#Create Matching column which stores index of first matched list
df2['Matching'] = np.nan
#Create Column Stating Status of Matching
df2['Status'] = 'No Match'

#Code for finding the exact matches and assigning indices in Matching column
for index1,lst1 in enumerate(df2['dummy']):
    for index2,lst2 in enumerate(df2['dummy']):
        if index1<index2:
            if (lst1 == lst2):
                if np.isnan(df2.loc[index2,'Matching']):
                    df2.loc[index1,'Matching'] = index1
                    df2.loc[index2,'Matching'] = index1
                    df2.loc[[index1,index2],'Status'] = 'Fully Matched'
            else:
                count = sum([1 for v1 in lst1 for v2 in lst2 if v1==v2])
                if count>=2:
                    if np.isnan(df2.loc[index2,'Matching']):
                        df2.loc[index1,'Matching'] = index1
                        df2.loc[index2,'Matching'] = index1
                        df2.loc[[index1,index2],'Status'] = 'Partially Matched'

#Finding the sum of total exact matches
print(df2['Matching'].notnull().sum())

7

#Deleting the dummy column
del df2['dummy']

#Final Dataframe
print(df2)

  ID                   Productdetailed  Matching             Status
0  1               [Phone, Watch, Pen]       0.0      Fully Matched
1  2            [Pencil, fork, Eraser]       1.0      Fully Matched
2  3            [Apple, Mango, Orange]       2.0  Partially Matched
3  4  [Something, Nothing, Everything]       NaN           No Match
4  5            [Eraser, fork, Pencil]       1.0      Fully Matched
5  6               [Phone, Watch, Pen]       0.0      Fully Matched
6  7                    [Apple, Mango]       2.0  Partially Matched
7  8               [Pen, Phone, Watch]       0.0      Fully Matched

要知道精确匹配:

df2["Productdetailed"]=df2["Productdetailed"].sort_values()
# create new colum from the sorted list. More easy to work with pivot table
df2['Productdetailed_str'] = df2['Productdetailed'].apply(lambda x: ', '.join(x))
df2["hit"] = 1
df3 = (df2.pivot_table(index=["Productdetailed_str"],
                 values=["ID", "hit"],
                aggfunc={'ID': lambda x: ', '.join(x), 'hit': 'sum'}
               ))

Hit是出现的次数。 结果df3:

                                  ID  hit
Productdetailed_str                      
Apple, Mango                       7    1
Apple, Mango, Orange               3    1
Eraser, fork, Pencil               5    1
Pen, Phone, Watch                  8    1
Pencil, fork, Eraser               2    1
Phone, Watch, Pen               1, 6    2
Something, Nothing, Everything     4    1

部分匹配比较困难,但您可以开始拆分列表并使用数据透视表:

test = df2.apply(lambda x: pd.Series(x['Productdetailed']),axis=1).stack().reset_index(level=1, drop=True).to_frame(name='list').join(df2)

如果你运行测试。在“list column”中有“Productdetailed column”列表中的单词。还有,你有身份证。。。所以我认为使用pivot表可以提取信息。。你知道吗

相关问题 更多 >

    热门问题