我的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
我想做的是:
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的两个值,因为它们彼此不相邻。
我所做的事情:
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]。
答案 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使用cumsum
和diff
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)