问题描述
# create example df
df = pd.DataFrame(index=[1,2,3,4,5,6,7,8])
df['ID'] = [1,1,2]
df['election_date'] = pd.date_range("01/01/2010",periods=8,freq="M")
df['status'] = ['b','a','b','c','d','b']
# sort values
df.sort_values(['election_date'],inplace=True,ascending=False)
df.reset_index(drop=True,inplace=True)
df
ID election_date status
0 2 2010-08-31 b
1 2 2010-07-31 d
2 2 2010-06-30 d
3 2 2010-05-31 a
4 1 2010-04-30 c
5 1 2010-03-31 b
6 1 2010-02-28 a
7 1 2010-01-31 b
我想为每个 status
获取列 ID
的累积最频繁状态。这是我所期望的:
ID election_date status cum_most_freq_status
0 2 2010-08-31 b d
1 2 2010-07-31 d d
2 2 2010-06-30 d a
3 2 2010-05-31 a NaN
4 1 2010-04-30 c b
5 1 2010-03-31 b a
6 1 2010-02-28 a b
7 1 2010-01-31 b NaN
解释:
-
2010-01-31
的值为NaN
,因为过去没有status
值。2010-05-31
也是如此。 - 对于
2010-03-31
,过去最频繁的状态是 a 和 b。因此,我们采用最新的值,即a
。
你会怎么做?
解决方法
您可以先创建一个以 ID
和 election_date
为索引的 DataFrame,以及单热编码的 status
值,然后计算 cumsum
。
如果计数相同,我们想选择最近的状态,所以我在当前状态的 cumsum
中添加了一个小数(小于 1),所以当我们应用 {{1 }} 它将获取最新的状态,以防出现平局。
在使用 idxmax
找到最频繁的累积状态后,我们可以使用原始 DataFrame idxmax
:
merge
输出:
# make one-hot-encoded status dataframe
z = (df
.groupby(['ID','election_date','status'])
.size().unstack().fillna(0))
# break ties to choose most recent
z = z.groupby(level=0).cumsum() + (z * 1e-4)
# shift by 1 row,since we only count previous status occurrences
z = z.groupby(level=0).shift()
# merge
df.merge(z.idxmax(axis=1).to_frame('cum_most_freq_status').reset_index())