获取 pandas 数据框中特定列的累积最频繁状态

问题描述

我有一个数据框:

# 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

你会怎么做?

解决方法

您可以先创建一个以 IDelection_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())