应用groupby后如何创建单独的df?

时间:2019-04-27 17:36:52

标签: python-3.x pandas

我的df如下:

Product Step
1   1
1   3
1   6
1   6
1   8
1   1
1   4
2   2
2   4
2   8
2   8
2   3
2   1
3   1
3   3
3   6
3   6
3   8
3   1
3   4

我想做的是:

  1. 对于每个Product,每个Step都必须被抓取,并且顺序不得更改,也就是说,如果我们看一下产品1,则在第8步之后有1,而那个1必须仅在8点之后。因此,产品1和产品3的预期输出应为以下顺序:1、3、6、8、1、4;对于产品2,它必须为:2、4、8、3、1。

更新: 在这里,我只想要乘积1和乘积3的值为6,因为在主df中,乘积6彼此相邻,但是必须同时存在乘积1的两个值,因为它们彼此不相邻。

  1. 完成第一步后,必须将具有相同步骤的产品分组到一个新的df中(在下面的示例中:产品1和3具有相同的步骤,因此必须将它们分组在一起)

我所做的事情:

import pandas as pd
sid = pd.DataFrame(data.groupby('Product').apply(lambda x: x['Step'].unique())).reset_index()

但是它产生的结果是:

    Product 0
0   1   [1 3 6 8 4]
1   2   [2 4 8 3 1]
2   3   [1 3 6 8 4]

这不是我想要的结果。我希望第一个和第三个乘积的值是[1 3 6 8 1 4]。

3 个答案:

答案 0 :(得分:2)

groupby保留了组中行的顺序,因此不必担心行移位。

apply(tuple)来说,一个简单但不那么有效的解决方案是,因为它们是可哈希的,因此您可以对它们进行分组以查看哪些产品相同。 form_seq将使其成为连续的值,以便在形成元组之前在步骤列表中仅出现一次。

def form_seq(x):
    x = x[x != x.shift()]
    return tuple(x)

s = df.groupby('Product').Step.apply(form_seq)
s.groupby(s).groups

#{(1, 3, 6, 8, 1, 4): Int64Index([1, 3], dtype='int64', name='Product'),
# (2, 4, 8, 3, 1): Int64Index([2], dtype='int64', name='Product')}

或者如果您想要一个DataFrame:

s.reset_index().groupby('Step').Product.apply(list)
#Step
#(1, 3, 6, 8, 1, 4)    [1, 3]
#(2, 4, 8, 3, 1)          [2]
#Name: Product, dtype: object

该词典的值是共享步骤序列的产品分组(由词典键给定)。产品1和3通过步骤序列1, 3, 6, 8, 1, 4分组在一起。

答案 1 :(得分:2)

IIUC使用cumsumdiff

创建新密钥
df['Newkey']=df.groupby('Product').Step.apply(lambda x : x.diff().ne(0).cumsum())
df.drop_duplicates(['Product','Newkey'],inplace=True)
s=df.groupby('Product').Step.apply(tuple)
s.reset_index().groupby('Step').Product.apply(list)
Step
(1, 3, 6, 8, 1, 4)    [1, 3]
(2, 4, 8, 3, 1)          [2]
Name: Product, dtype: object

答案 2 :(得分:0)

另一种非常相似的方式:

df_no_dups=df[df.shift()!=df].dropna(how='all').ffill()
df_no_dups_grouped=df_no_dups.groupby('Product')['Step'].apply(list)