Python 通过求和和和连接进行分组
我有一个如下的数据帧Python 通过求和和和连接进行分组,python,pandas,pandas-groupby,Python,Pandas,Pandas Groupby,我有一个如下的数据帧 +-----------+----------+-----+ | InvoiceNo | ItemCode | Qty | +-----------+----------+-----+ | Inv-001 | c | 1 | +-----------+----------+-----+ | Inv-001 | b | 2 | +-----------+----------+-----+ | Inv-001 | a
+-----------+----------+-----+
| InvoiceNo | ItemCode | Qty |
+-----------+----------+-----+
| Inv-001 | c | 1 |
+-----------+----------+-----+
| Inv-001 | b | 2 |
+-----------+----------+-----+
| Inv-001 | a | 1 |
+-----------+----------+-----+
| Inv-002 | a | 3 |
+-----------+----------+-----+
| Inv-002 | b | 1 |
+-----------+----------+-----+
| Inv-002 | c | 1 |
+-----------+----------+-----+
| Inv-002 | d | 4 |
+-----------+----------+-----+
| Inv-002 | a | 1 |
+-----------+----------+-----+
| Inv-003 | e | 1 |
+-----------+----------+-----+
| Inv-003 | b | 2 |
+-----------+----------+-----+
我想计算每个InvoiceNo
wise项目组合。i、 e.每个ItemCode
的总和。排序并连接到一个字符串。
注:在Inv-002
产品a
中有两行
我的期望/要求输出如下
+-----------+--------------------+
| InvoiceNo | Desired result |
+-----------+--------------------+
| Inv-001 | a-1, b-2, c-1 |
+-----------+--------------------+
| Inv-002 | a-4, b-1, c-1, d-4 |
+-----------+--------------------+
| Inv-003 | b-2, e-1 |
+-----------+--------------------+
到目前为止,我已经编写了以下代码
#load data
df = pd.read_excel('data.xlsx')
#groupby and sum
g = df.groupby(['InvoiceNo','ItemCode']).sum()
# Codes to convert the MultiIndex to a regualr dataframe
g = g.unstack(fill_value=0)
g.reset_index(drop=True,inplace=True)
g = g.droplevel(level=0, axis=1).fillna(0)
#calculation
g.dot(g.columns+',').str[:-1]
下面是我得到的结果。所有的物品都分开了
+---+---------------------+
| 0 | a,b,b,c |
+---+---------------------+
| 1 | a,a,a,a,b,c,d,d,d,d |
+---+---------------------+
| 2 | b,b,e |
+---+---------------------+
请指导我解决这个问题。
groupby
两次。第一个获取每个['InvoiceNo','ItemCode']
的总和。然后,我们将代码和类别与发票上的“-”和组连接在一起,以创建完整的字符串
df1 = df.groupby(['InvoiceNo', 'ItemCode'])['Qty'].sum().reset_index('ItemCode')
df1 = df1['ItemCode'].str.cat(df1['Qty'].astype(str), '-').groupby(level=0).agg(', '.join)
#InvoiceNo
#Inv-001 a-1, b-2, c-1
#Inv-002 a-4, b-1, c-1, d-4
#Inv-003 b-2, e-1
#Name: ItemCode, dtype: object
你会注意到我不需要整理任何东西。这是因为默认情况下,
groupby
会对分组键进行排序,因此在第一行之后,系列将保证按照['InvoiceNo','ItemCode']
进行排序,这是我们在','之前想要的。加入这里您可以:
df1=df.groupby(['InvoiceNo','ItemCode',sort=False).Qty.sum().reset_index()
df1['Desired result']=df1.ItemCode+'-'+df1.Qty.astype(str)
打印(df1.groupby(['InvoiceNo'])['Desired result'].apply(lambda res:','.join(sorted(res)).reset_index())
输出:
InvoiceNo Desired result
0 Inv-001 a-1, b-2, c-1
1 Inv-002 a-4, b-1, c-1, d-4
2 Inv-003 b-2, e-1
如果我们在dataframe
上执行由数千行组成的多个Groupby
,在速度上是否有任何警告或妥协?@RaptoGroupby
通常性能非常好,许多基本聚合,如sum
,都有非常快速的实现,所以,即使你有100万组和5000万行,也只需要一秒钟。另一方面,如果您groupby
+应用您自己的函数,该函数将成为组上的循环。这通常会稍微慢一点,并随着组数的增加而扩展,但应该仍然可以。我不确定如何实现str.join
,它可能会慢一点,但使用字符串操作通常会慢一点。看来我不会面临任何性能问题。因为我的数据每个文件最多包含10万行。如果我一个文件一个文件地处理。希望事情会顺利的。@Alolz我有一个类似的例子。然而,上面的ItemCode
对应的是数字。当我应用你的代码时,我得到了一个错误。有什么建议吗?@Tommy如果你试图对一个数字进行字符串运算,你会出错的。因此,您首先需要将其转换为字符串:df1['ItemCode']=df1['ItemCode'].astype(str)
,然后您可以加入并执行任何其他您想要的操作。谢谢您,并向上投票。我接受了@ALollz的回答,因为它很优雅。。