在 python 数据帧熊猫中找到相同的组

时间:2021-04-26 15:37:38

标签: python pandas dataframe pandas-groupby

我试图在我的数据框中找到与此类似的相同订单 -

Order_ID |SKU |Qty |

123 | A | 1 |

123 | B | 2 |

345 | A | 1 |

345 | B | 2 |

678 | A | 1 |

678 | C | 3 |

一个订单中可以有多个SKU,即1个订单可以有多行。 因此包含确切 SKU 和数量的 order_ID 是相同的。这里是 123 和 345。 我需要与 SKU 和数量相同的订单。

如何使用分组在 Pandas 数据框中实现这一点?

样本输出类似于 -

Order_ID     |   SKU    | Qty        |Unique_Orders
[123] , [345]| [A],[B]  | [1],[2]    |2
[678]        | [A],[C]  | [1],[3]    |1

感谢您的帮助。

5 个答案:

答案 0 :(得分:2)

更新

基于问题的更新,这里是更新的答案,没有任何 Python 级循环:

skuqty = df.groupby('Order_ID')[['SKU', 'Qty']].agg(tuple).reset_index()
skuqty.groupby(['SKU', 'Qty'])['Order_ID'].unique().reset_index()

给出:

      SKU     Qty    Order_ID
0  (A, B)  (1, 2)  [123, 345]
1  (A, C)  (1, 3)       [678]

或者,如果您想完全匹配您的规格,您可以进一步执行以下操作:

z = skuqty.groupby(['SKU', 'Qty'])['Order_ID'].unique().reset_index()
z = z.assign(SKU=z['SKU'].apply(list)).assign(Qty=z['Qty'].apply(list)).assign(Unique_Orders=z['Order_ID'].apply(len))
z = z[['Order_ID', 'SKU', 'Qty', 'Unique_Orders']]

给出:

>>> z
     Order_Id     SKU     Qty  Unique_Orders
0  [123, 345]  [A, B]  [1, 2]              2
1       [678]  [A, C]  [1, 3]              1

速度

这相对较快:

n = 1_000_000
df = pd.DataFrame({
    'Order_ID': np.random.randint(0, 999, n),
    'SKU': np.random.choice(list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'), n),
    'Qty': np.random.randint(1, 100, n),
})

%timeit proc(df)  # which is the (first) code above
# 405 ms ± 407 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

原答案

这取决于您想对组做什么。下面是一个对 Qty 求和的示例:

df.groupby('Order_ID')['Qty'].sum()

给出:

Order_ID
123    3
345    3
678    4
Name: Qty, dtype: int64

或者,如果您想同时查看 Qty 总数和不同的 SKU

>>> df.groupby('Order_ID').agg({'Qty':sum, 'SKU':'unique'})
          Qty     SKU
Order_ID             
123         3  [A, B]
345         3  [A, B]
678         4  [A, C]

最后,有一个可以为每个 dict 提供 {SKU: Qty}Order_ID

>>> df.groupby('Order_ID').apply(lambda g: dict(g[['SKU', 'Qty']].values))
Order_ID
123    {'A': 1, 'B': 2}
345    {'A': 1, 'B': 2}
678    {'A': 1, 'C': 3}

答案 1 :(得分:2)

我们可以使用 groupby + unique 来获取每个 SKUQty 的唯一订单

df.groupby(['SKU', 'Qty'])['Order_ID'].unique()

如果您还想countunique的订单,那么我们可以额外使用nunique

df.groupby(['SKU', 'Qty'])['Order_ID'].agg(['unique', 'nunique'])

                  unique  nunique
SKU Qty                          
A   1    [123, 345, 678]        3
B   2         [123, 345]        2
C   3              [678]        1

答案 2 :(得分:1)

df.groupby(['SKU', 'Qty'])['Order_ID'].apply(list)

答案 3 :(得分:1)

另一个版本:

x = df.groupby("Order_ID")[["SKU", "Qty"]].apply(
    lambda x: frozenset(zip(x.SKU, x.Qty))
)

df_out = pd.DataFrame(
    [
        {
            "Order_ID": v.to_list(),
            "SKU": [sku for sku, _ in k],
            "Qty": [qty for _, qty in k],
            "Unique_Orders": len(v),
        }
        for k, v in x.index.groupby(x).items()
    ]
)
print(df_out)

打印:

     Order_ID     SKU     Qty  Unique_Orders
0  [123, 345]  [A, B]  [1, 2]              2
1       [678]  [C, A]  [3, 1]              1

答案 4 :(得分:0)

在这种情况下您不需要使用组。只需使用 pandas 中的 duplicated() 函数即可。

df.duplicated()

这将返回一个布尔系列,其中第一个重复值显示为 True,其他类似值跟随第一个为 False。

因此,如果您想检索重复的 ID,只需遵循正常的 Pandas 条件即可。

df['Order_ID'].loc[df.duplicated()].values.unique()

假设 Order_ID 是 DataFrame 中的一列,并且默认的 id 列仍然存在。

相关问题