【问题标题】:Is there a simpler way to get object from groupby and putting in dictionary?有没有更简单的方法从 groupby 获取对象并放入字典?
【发布时间】:2021-11-12 03:49:39
【问题描述】:

所以我的数据框如下所示: 我试图找到一种更简单的方法来从 Groupby 获取对象,然后将其放入字典中。 我必须获取索引,然后执行 for 循环以获取 Product 中每一行的确切字符串。

如果需要,请提供更多详细信息: 我的目标是找到重复的订单 ID,然后从列中取出产品并添加到字典中:

  • = 产品

  • 价值 = 产品被发现一起订购的次数

(我不是在寻找优化查找重复项的方法,我知道我可以使用df.duplicated

代码:

for date, df in df1.groupby('Order Date'):
    
    if  df.Product.count() > 1:

        indice = df.Product.index
        for data in indice:
            product = df.loc[data].at['Product']
            #update dictionary counter
            product_dict[product] = product_dict.get(product) + 1
      
    else:
        continue

为方便起见,您可以改用此 df。我列为字典:

{'Order ID': ['147268', '148041', '149343', '149964', '149350', '141732', '149620', '142451', '146039', '143498', '141316', '144804', '144804', '145270', '142789'],
 'Product': ['Wired Headphones', 'USB-C Charging Cable', 'Apple Airpods Headphones', 'AAA Batteries (4-pack)', 'USB-C Charging Cable', 'iPhone', 'Lightning Charging Cable', 'AAA Batteries (4-pack)', '34in Ultrawide Monitor', 'AA Batteries (4-pack)', 'AAA Batteries (4-pack)', 'Wired Headphones', 'iPhone', 'Google Phone', 'AAA Batteries (4-pack)']}

预期输出:

{“有线耳机”:8090,“USB-C 充电线”:9425,“Apple Airpods 耳机”:6374,“AAA 电池(4 件装)”:8266,“iPhone”:3663,“闪电充电”电缆':9074,'34 英寸超宽显示器':2500,'AA 电池(4 包)':8167,'Google 手机':3091,'Macbook Pro 笔记本电脑':1878,'ThinkPad 笔记本电脑':1605,'27 英寸 FHD显示器”:3010,“Bose SoundSport 耳机”:5459,“平板电视”:1827,“27 英寸 4K 游戏显示器”:2457,“LG 烘干机”:257,“20 英寸显示器”:1635,“LG 洗衣机”:268 , 'Vareebadd 电话': 1120}

【问题讨论】:

  • 欢迎来到 Stack OverFlow!请不要发布数据的图像,因为我们无法测试它们。相反,直接在代码块中发布 DataFrame (df) 的示例和预期的输出。一个好方法是将print(df.to_dict(orient=‘list’)) 的输出与print(df) 共享。这使我们能够轻松重现您的问题并为您提供帮助。
  • 非常感谢您的快速响应和欢迎。我将我的数据框缩小为一个较小的数据框,因为原始数据框太大而无法粘贴为 dict。
  • 谢谢,现在好多了!但是预期的输出也有助于确认我是否正确理解了问题。我的回答是否产生了预期的输出?

标签: python pandas dataframe pandas-groupby


【解决方案1】:
# number of products per order 
prods_per_order = df.groupby(['Order ID'])["Product"].transform("count")

res = ( 
    df.loc[prods_per_order > 1, "Product"]   # Select only the products that were ordered together with another(s) product(s)
      .value_counts()      # count how many times were per product 
      .to_dict()           # convert the result to a dict 
)

输入

df = pd.DataFrame({
    'Order ID': ['147268', '148041', '149343', '149964', '149350', 
                 '141732', '149620', '142451', '146039', '143498', 
                 '141316', '144804', '144804', '145270', '142789'],
     'Product': ['Wired Headphones', 'USB-C Charging Cable', 'Apple Airpods Headphones', 
                 'AAA Batteries (4-pack)', 'USB-C Charging Cable', 'iPhone', 
                 'Lightning Charging Cable', 'AAA Batteries (4-pack)', '34in Ultrawide Monitor', 
                 'AA Batteries (4-pack)', 'AAA Batteries (4-pack)', 'Wired Headphones', 
                 'iPhone', 'Google Phone', 'AAA Batteries (4-pack)']
})

df = df.sort_values(['Order ID', 'Product'])
>>> df 

   Order ID                   Product
10   141316    AAA Batteries (4-pack)
5    141732                    iPhone
7    142451    AAA Batteries (4-pack)
14   142789    AAA Batteries (4-pack)
9    143498     AA Batteries (4-pack)
11   144804          Wired Headphones  # <-- Note that only these two products
12   144804                    iPhone  # <--    were ordered together 
13   145270              Google Phone
8    146039    34in Ultrawide Monitor
0    147268          Wired Headphones
1    148041      USB-C Charging Cable
2    149343  Apple Airpods Headphones
4    149350      USB-C Charging Cable
6    149620  Lightning Charging Cable
3    149964    AAA Batteries (4-pack)

输出

>>> res

{'iPhone': 1, 'Wired Headphones': 1}

【讨论】:

  • 是的,这几乎是我想要的,所以对于字典来说,它基本上是:{ Product: } 所以只要在 df 中有一个重复的 Order ID 和 2不同的产品,这意味着这些产品是一起购买的。因此我会添加到字典中。你可以看到我想要的输出,我现在添加了。谢谢
  • 关于上一条评论的更多说明:我会将这两种产品都添加到字典中,例如如果耳机的ID为10179,iphone的ID为10179,那么它们是一起买的。所以在我的字典里,iphone计数器会上升,耳机计数器也会上升。
  • 还有哈利,如果你能解释一下你的单行会有帮助: res = df2.groupby('Order ID')['Product'].value_counts().loc[lambda counts: counts > 1].to_dict() 所以从我目前的理解来看:我们从值计数中得到唯一值的计数,这个值是否被用作 lambda 函数中的参数?并且 lamda 返回一个布尔值?
  • @Sleepelite 我想我终于明白你想要什么了。我误解了这个问题。我会尽快用正确的解决方案更新我的答案!
  • 哇,谢谢@HarryPlotter,这正是我所需要的,而且解释得很好!
【解决方案2】:

也许我误解了,但这似乎可以通过使用 Counter 来实现您想要实现的目标:

from collections import Counter

mask = (
    df.groupby(["Order Date", "Order ID"], sort=False)["Product"]
      .transform("count")
      .gt(1)
)
product_dict = Counter(df.loc[mask, "Product"])

稍作修改的示例数据框的结果(添加了Order Date 列)

   Order Date Order ID                   Product
0  2021-11-11   147268          Wired Headphones
1  2021-11-11   148041      USB-C Charging Cable
2  2021-11-11   149343  Apple Airpods Headphones
3  2021-11-11   149964    AAA Batteries (4-pack)
4  2021-11-11   149350      USB-C Charging Cable
5  2021-11-12   141732                    iPhone
6  2021-11-12   149620  Lightning Charging Cable
7  2021-11-12   142451    AAA Batteries (4-pack)
8  2021-11-12   146039    34in Ultrawide Monitor
9  2021-11-12   143498     AA Batteries (4-pack)
10 2021-11-12   141316    AAA Batteries (4-pack)
11 2021-11-12   144804          Wired Headphones
12 2021-11-12   144804                    iPhone
13 2021-11-12   145270              Google Phone
14 2021-11-12   142789    AAA Batteries (4-pack)

Counter({'Wired Headphones': 1, 'iPhone': 1})

也许groupby 超过Order ID 就足够了,但由于您分组超过Order Date,我怀疑它不是。

【讨论】:

  • 所以基本上我想要的字典是:{ Product: } 所以只要在 df 中有一个重复的 Order ID 和 2 个不同的产品,就意味着这些产品被购买了一起。因此我会添加到字典中。你可以看到我想要的输出,我现在添加了。谢谢
  • 我意识到你的代码也给了我我需要的输出,我没有马上理解代码所以没有意识到。非常感谢您的帮助 Timus。
猜你喜欢
  • 2021-05-31
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 1970-01-01
  • 2019-12-07
  • 1970-01-01
  • 2018-01-16
  • 1970-01-01
相关资源
最近更新 更多