【问题标题】:Get Only Few Elements of a Group in Pandas在 Pandas 中仅获取组的少数元素
【发布时间】:2019-09-08 09:25:36
【问题描述】:

我有一个按 Pandas 分组的数据框:

id    date    temperature
1  2011-9-12   12
   2011-9-12   20
   2011-9-18   12
   2011-9-19   90
2  2011-9-12   15
3  2011-9-12   15
   2011-9-16   15

这里,每个id都有不同数量的温度记录。

我想修复它们,比如每个 id 的平均记录数(比如 3 个)。如果缺少某些记录,我想一开始就输入零。

我想保留最近的记录。

即我的最终数据框应该是:

id    temperature
1     20
      12
      90
2     0
      0
      15
3     0
      15
      15

这是在线给出错误的numpy代码:

s=df.groupby(level=0)['temperature'].apply(list)
s1=s.tolist()
arr = np.zeros((len(s1),3),int)
lens = [3-len(l) for l in s1]
mask = np.arange(3) >=np.array(lens)[:,None]
arr[mask] = np.concatenate(s1) ## Error
    pd.DataFrame({'id':s.index.repeat(3),'temperature':arr.ravel()})

我怀疑这个错误是由于我的数据可能有超过 3 行的 id。

如何解决这个问题?

【问题讨论】:

  • 您想要随机 n 条记录还是唯一记录?
  • @AkshayNevrekar 我想保留最近的 n 条(比如 3 条)记录,如果不可行,则将 0 放在上面的示例中。谢谢,我已经编辑了问题以避免混淆。

标签: python pandas numpy pandas-groupby


【解决方案1】:

使用GroupBy.cumcountascending=False 作为计数器,Series.reindex by MultiIndexMultiIndex.from_product 创建:

print (df)
   id       date  temperature
0   1  2011-9-12           12
1   1  2011-9-12           20
2   1  2011-9-18           12
3   1  2011-9-19           90
4   2  2011-9-12           15
5   3  2011-9-12           15
6   3  2011-9-16           15

N = 3
df['new'] = df.groupby('id').cumcount(ascending=False)
mux = pd.MultiIndex.from_product([df['id'].unique(), range(N-1, -1, -1)], names=['id','new'])
df1 = (df.set_index(['id', 'new'])['temperature']
        .reindex(mux, fill_value=0)
        .reset_index(level=1, drop=True)
        .reset_index())

print (df1)
   id  temperature
0   1           20
1   1           12
2   1           90
3   2            0
4   2            0
5   2           15
6   3            0
7   3           15
8   3           15

编辑:

如果多索引DataFrame:

print (df)
              temperature
id date                  
1  2011-9-12           12
   2011-9-12           20
   2011-9-18           12
   2011-9-19           90
2  2011-9-12           15
3  2011-9-12           15
   2011-9-16           15

print (df.index)
MultiIndex(levels=[[1, 2, 3], ['2011-9-12', '2011-9-16', '2011-9-18', '2011-9-19']],
           codes=[[0, 0, 0, 0, 1, 2, 2], [0, 0, 2, 3, 0, 0, 1]],
           names=['id', 'date'])

N = 3
df['new'] = df.groupby('id').cumcount(ascending=False)
mux = pd.MultiIndex.from_product([df.index.levels[0], range(N-1, -1, -1)], names=['id','new'])
df1 = (df.reset_index(level=1, drop=True)
         .set_index('new', append=True)['temperature']
         .reindex(mux, fill_value=0)
         .reset_index(level=1, drop=True)
         .reset_index())

print (df1)
   id  temperature
0   1           20
1   1           12
2   1           90
3   2            0
4   2            0
5   2           15
6   3            0
7   3           15
8   3           15

【讨论】:

  • 谢谢,但我再次得到同样的错误 keyerror: set_index(''new, append=True)['id'] -> keyerror id
  • @tstseby - 表示没有列ACCTNBRprint (df.info) 是什么?
  • @tstseby - 列名中也可能有一些空格,请通过print (df.columns.tolist())检查它
  • 是的,id 列没有出现在 df.columns.tolist() 中(只出现新的和“温度”),但是,它出现在 df.index 中(有两个名称:“id” '和'日期')
  • @tstseby - 尝试删除最后一个 `.reset_index()` - 但因为没有 MultiIndex,所以值会重复。如果 rmove last .reset_index(level=1, drop=True) .reset_index() 也获得计数器级别,并且第一个 id 不重复。
【解决方案2】:

一个有点冗长但有效的解决方案:

df.groupby('id').apply(lambda x: x.sort_values(by='date'))
                .drop('id', axis=1)['temperature'].groupby(level=0).tail(3)
                .groupby(level=0).apply(lambda x: np.pad(x, (3-len(x),0), 'constant'))
                .reset_index()

   id   temperature
0   1  [20, 12, 90]
1   2    [0, 0, 15]
2   3   [0, 15, 15]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    • 2014-10-17
    • 1970-01-01
    • 2019-09-11
    • 2022-01-08
    相关资源
    最近更新 更多