Python-使用反向计数器附加行号

时间:2018-10-23 16:32:16

标签: python pandas loops numpy

我还有另一个Python问题。可能可以通过循环来实现这一目标,但是我一直在寻找更精简的解决方案

假设我有一个像这样的数据框:

enter image description here

我正在寻找一个代码来生成列ID,该代码不超过当Sold列中的值更改时的降序计数器-即,对于每个推销员,我希望ID列检索剩余的天数,直到卖价发生变化。 例如,在2018年1月1日,推销员Joe的ID = 2,因为信号在2天内发生了变化。

关于如何解决这个问题的任何想法?

非常感谢。 J

1 个答案:

答案 0 :(得分:1)

设置:

df = pd.DataFrame([
    pd.Series(pd.date_range('1/1/2018', '1/7/2018').append(pd.date_range('1/1/2018', '1/7/2018'))),
    pd.Series(['Joe']*7 + ['Helen']*7),
    pd.Series([1,1,0,0,0,0,1,0,1,1,0,1,0,0]),
]).T
df.columns = ['date', 'salesman', 'sold']
df['date'] = pd.to_datetime(df['date'])

计算:

df['changes'] = df.groupby('salesman')['sold'].expanding().apply(lambda x: (np.diff(x) != 0).sum()).reset_index(drop = True)

df['id'] = df.groupby(['salesman', 'changes']).apply(lambda grp: pd.Series(len(grp) - grp.sort_values('date').reset_index().index)).reset_index(drop = True)

df.drop('changes', axis = 1, inplace = True)

结果:

>>> df


    date    salesman  sold  id
0   2018-01-01  Joe     1   2
1   2018-01-02  Joe     1   1
2   2018-01-03  Joe     0   4
3   2018-01-04  Joe     0   3
4   2018-01-05  Joe     0   2
5   2018-01-06  Joe     0   1
6   2018-01-07  Joe     1   1
7   2018-01-01  Helen   0   1
8   2018-01-02  Helen   1   2
9   2018-01-03  Helen   1   1
10  2018-01-04  Helen   0   1
11  2018-01-05  Helen   1   1
12  2018-01-06  Helen   0   2
13  2018-01-07  Helen   0   1

说明:

创建一个'changes'列,该列在每次销售人员的'sold'字段每次更改时递增。然后,对于每个增量组(仍按销售人员分组),获取该组的长度(等于该值的后续行的数量),并从该值中减去按日期排序的每一行的索引。减法的结果将是一个从组的长度降到1的序列。重置索引并合并回到原始数据帧。这是一个令人困惑的解决方案,但它应该可以工作。