【问题标题】:Complicated Split Apply Combine复杂的拆分应用组合
【发布时间】:2018-04-15 20:49:09
【问题描述】:

我有以下数据框:

arrays = [np.array(['1', '1', '1', '2', '2', '2', '3', '3', '3', '4', '4', '4']),
          np.array(['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C'])]
df = pd.DataFrame(np.random.randn(12, 3), index=arrays, columns=['Column1', 'Column2', 'Column3'])
df.index.names = ['Index1', 'Index2']

看起来像这样:

                 Column1    Column2     Column3
Index1  Index2          
1         A     -0.218251    1.744845   -0.241300
          B      1.107614   -0.059469    0.952544
          C      0.203066    0.412727    0.057129
2         A      0.432153    0.568879   -1.014900
          B     -0.713515   -0.790029    1.530333
          C      0.547787   -0.161020    0.078548
3         A      0.425833   -0.316999   -0.516260
          B      0.980780    0.844847    1.097464
          C     -1.724548    0.199910    0.961234
4         A      0.130533   -1.249353   -0.848859
          B     -0.674836    1.404397    1.258285
          C      0.741651    1.578671   -1.411311

我想做的是拆分/应用/组合并返回一个如下所示的数据框:

                 Column1    Column2     Column3
Index1  Index2          
1         B      1.107614   -0.059469    0.952544
          C      0.203066    0.412727    0.057129
2         B     -0.713515   -0.790029    1.530333
          C      0.547787   -0.161020    0.078548
3         A      0.425833   -0.316999   -0.516260
          B      0.980780    0.844847    1.097464
4         A      0.130533   -1.249353   -0.848859
          B     -0.674836    1.404397    1.258285

它在这里所做的是在时间 1(在本例中为 B 和 C)基于 Column1 取 A/B/C 中最大的两个。它只保留这两个时间 1 和 2。

然后在时间 3,它再次根据第 1 列(这次是 A 和 B)取 A/B/C 中最大的两个,然后在时间 3 和 4 中保留这两个。

有没有办法使用 groupby、nlargest 和其他任何函数来执行此操作?需要自定义函数吗?

【问题讨论】:

  • 您可能希望在顶部设置一个随机种子,以便尝试解决问题的人获得与您相同的数字。
  • 我的意思是,数字本身并不是很重要。我只想根据最高值进行过滤。

标签: python pandas pandas-groupby


【解决方案1】:

我将逐个对象遍历一个组,将loc中我需要的元组拼凑在一起

def f(gt):
    n, d = gt
    midx = d.index.remove_unused_levels()
    xidx = d.loc[midx.levels[0][0], 'Column1'].nlargest(2).index
    return [(lv, mx) for lv in midx.levels[0] for mx in xidx]

g = pd.factorize(df.index.get_level_values(0))[0] // 2
grp = df.groupby(g)

df.loc[sum(map(f, grp), [])]

                Column1   Column2   Column3
Index1 Index2                              
1      B       1.107614 -0.059469  0.952544
       C       0.203066  0.412727  0.057129
2      B      -0.713515 -0.790029  1.530333
       C       0.547787 -0.161020  0.078548
3      B       0.980780  0.844847  1.097464
       A       0.425833 -0.316999 -0.516260
4      B      -0.674836  1.404397  1.258285
       A       0.130533 -1.249353 -0.848859

详情

def f(gt):
    # When iterating through the group by object
    # we will get tuples like (name_of_group, dataframe_slice)
    n, d = gt

    # A MultiIndex after slicing will have level values that
    # will get in the way of the things I'm doing.  So I remove them
    midx = d.index.remove_unused_levels()

    # I `loc` on the first value of the first level.  This removes
    # the first level for the resulting slice.
    # When I use nlargest, the resulting index will only be a ref
    # to the index values without the first level.
    xidx = d.loc[midx.levels[0][0], 'Column1'].nlargest(2).index

    # Then I return a list of tuples to stitch all values from the
    # first level to those values from the largest ones from the
    # first group.
    return [(lv, mx) for lv in midx.levels[0] for mx in xidx]

# Using factorize here to group the entire data frame into pairs
# by that first level
g = pd.factorize(df.index.get_level_values(0))[0] // 2
grp = df.groupby(g)

# The summation concatenates all the lists of tuples into one list
df.loc[sum(map(f, grp), [])]

【讨论】:

  • 非常感谢您的回复!如果我想概括并采用每 m 个索引中最大的 n 个,我会分别更改这 2 个中的每一个吗?无论哪种方式,我都会尝试一下,看看效果如何!
猜你喜欢
  • 1970-01-01
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 2015-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多