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
,在速度上是否有任何警告或妥协?@Rapto
Groupby
通常性能非常好,许多基本聚合,如
sum
,都有非常快速的实现,所以,即使你有100万组和5000万行,也只需要一秒钟。另一方面,如果您
groupby
+
应用您自己的函数,该函数将成为组上的循环。这通常会稍微慢一点,并随着组数的增加而扩展,但应该仍然可以。我不确定如何实现
str.join
,它可能会慢一点,但使用字符串操作通常会慢一点。看来我不会面临任何性能问题。因为我的数据每个文件最多包含10万行。如果我一个文件一个文件地处理。希望事情会顺利的。@Alolz我有一个类似的例子。然而,上面的
ItemCode
对应的是数字。当我应用你的代码时,我得到了一个错误。有什么建议吗?@Tommy如果你试图对一个数字进行字符串运算,你会出错的。因此,您首先需要将其转换为字符串:
df1['ItemCode']=df1['ItemCode'].astype(str)
,然后您可以加入并执行任何其他您想要的操作。谢谢您,并向上投票。我接受了@ALollz的回答,因为它很优雅。。