比较字典的值并返回匹配值的计数
Posted
技术标签:
【中文标题】比较字典的值并返回匹配值的计数【英文标题】:Compare values of a dictionary and return a count of matching values 【发布时间】:2018-10-24 10:28:16 【问题描述】:我有一个字典,其中包含产品名称和购买了这些商品的唯一客户电子邮件,如下所示:
customer_emails =
'Backpack':['customer1@gmail.com','customer2@gmail.com','customer3@yahoo.com','customer4@msn.com'],
'Baseball Bat':['customer1@gmail.com','customer3@yahoo.com','customer5@gmail.com'],
'Gloves':['customer2@gmail.com','customer3@yahoo.com','customer4@msn.com']
我正在尝试迭代每个键的值并确定有多少电子邮件与其他键匹配。我将此字典转换为 DataFrame,并使用类似这样的方法得到了我想要的单列比较的答案
customers[customers['Baseball Bat'].notna() == True]['Baseball Bat'].isin(customers['Gloves']).sum()
我想要完成的是创建一个基本上看起来像这样的 DataFrame,以便我可以轻松地将它用于相关图表。
Backpack Baseball Bat Gloves
Backpack 4 2 3
Baseball Bat 2 3 1
Gloves 3 1 3
我正在考虑的方法是遍历 customer_emails
字典,但我不确定您将如何挑选一个键来将其值与所有其他键进行比较等等,然后存储它。
【问题讨论】:
如果您的字典列表大小不等,您如何创建customers
?
@cᴏʟᴅsᴘᴇᴇᴅ 您必须对其进行迭代并将值转换为熊猫系列。 customers = pd.DataFrame(dict([ (k,pd.Series(v)) for k,v in customer_emails.items() ]))
哦...那好吧,我已经在我的回答中向您展示了一种更好的方法。
哇,这是一种更好的转换方式。非常感谢
【参考方案1】:
使用相同的逻辑创建系列,然后我们使用intersection
作为列表
s=pd.Series(customer_emails)
pd.DataFrame(np.reshape([len(set(x).intersection(set(y)))for x in s for y in s ],(3,3)),index=s.index,columns=s.index)
Out[299]:
Backpack Baseball Bat Gloves
Backpack 4 2 3
Baseball Bat 2 3 1
Gloves 3 1 3
【讨论】:
【参考方案2】:以pd.DataFrame.from_dict
开头:
df = pd.DataFrame.from_dict(customer_emails, orient='index').T
df
Backpack Baseball Bat Gloves
0 customer1@gmail.com customer1@gmail.com customer2@gmail.com
1 customer2@gmail.com customer3@yahoo.com customer3@yahoo.com
2 customer3@yahoo.com customer5@gmail.com customer4@msn.com
3 customer4@msn.com None None
现在,使用stack
+ get_dummies
+ sum
+ dot
:
v = df.stack().str.get_dummies().sum(level=1)
v.dot(v.T)
Backpack Baseball Bat Gloves
Backpack 4 2 3
Baseball Bat 2 3 1
Gloves 3 1 3
或者,将stack
切换为melt
以提高性能。
v = (df.melt()
.set_index('variable')['value']
.str.get_dummies()
.sum(level=0)
)
v.dot(v.T)
variable Backpack Baseball Bat Gloves
variable
Backpack 4 2 3
Baseball Bat 2 3 1
Gloves 3 1 3
【讨论】:
【参考方案3】:您可以先找到每个产品的所有计数和对应的电子邮件,然后将结果字典传递给pd.DataFrame
:
import pandas as pd
emails = 'Baseball Bat': ['customer1@gmail.com', 'customer3@yahoo.com', 'customer5@gmail.com'], 'Backpack': ['customer1@gmail.com', 'customer2@gmail.com', 'customer3@yahoo.com', 'customer4@msn.com'], 'Gloves': ['customer2@gmail.com', 'customer3@yahoo.com', 'customer4@msn.com']
results = a:c:sum(h in j for h in b) for c, j in emails.items() for a, b in emails.items()
df = pd.DataFrame(results)
输出:
Backpack Baseball Bat Gloves
Backpack 4 2 3
Baseball Bat 2 3 1
Gloves 3 1 3
【讨论】:
以上是关于比较字典的值并返回匹配值的计数的主要内容,如果未能解决你的问题,请参考以下文章
将字典的键与 List 的值进行比较,并返回所有匹配的值,包括重复值