具有多个变量的分组依据

时间:2020-10-12 07:52:34

标签: python pandas group-by

我有一个看起来像这样的df:

Date   Animal   Height   Weight
Jan-00   Cat      102      56
Jan-00   Cat      98       75
Jan-00   Cat      50       100
Jan-00   Cat      46       46
Jan-00   Cat      100      50

我正在尝试查找1月00日猫的平均体重,该平均体重大于1月00日猫的平均身高。因此,在此示例中,中间高度为98;而猫的平均体重超过身高的中位数为53(平均值为50、56)。我有不同数量的不同动物类型,所以我不想手动指定动物类型。随着时间的推移,我还需要测量猫的重量以外的其他东西(因此,我正在尝试将来对我的代码进行某种程度的证明)。

从精练StackOverflow时,我的方法是: (1)写一个函数,告诉其余代码我要测量的东西:

def column_index(df, query_cols):
    cols = df.columns.values
    sidx = np.argsort(cols)
    return sidx[np.searchsorted(cols,query_cols,sorter=sidx)]

cols = (column_index(df, ["Weight"]))

然后(2),编写一些代码,将我的原始df分割为日期和动物类型,再除以中位数身高,然后返回我要测量的内容:

x = (df["Height"]
     .gt(df.groupby(["Date","Animal"])["Height"]
     .transform('median')))

df_Tall = df[x].mean(level = 0)[df.columns[cols]]

但是,当我这样做时,它仅返回重量的一系列数据;我正在尝试获取多个列,每个列代表不同的动物-即我的预期输出应如下所示:

       Weight
Date   Cat   Animal_x   Animal_y   Animal_z
Jan-00  53     xx          xx         xx 

我认为我的错误很喜欢

.gt(df.groupby(["Date","Animal"])["Height"]

但是我不知道如何解决它。任何想法将不胜感激!

谢谢

1 个答案:

答案 0 :(得分:0)

您的方法几乎是正确的。我刚刚添加了另一个groupby中值过滤后的高度数据,以AnimalDate列对平均体重(和身高)进行分组:

df.loc[
    df['Height'].gt(df.groupby(['Date', 'Animal'])['Height'].transform('median')), :
].groupby(['Date', 'Animal']).mean().unstack()

当然,您可以通过选择第二个Weight之后(或之前)的Weight列来获得groupby的均值。通过将最后一行更改为:].groupby(['Date', 'Animal'])[['Weight']].mean().unstack(),并用'Weight'周围的双括号保留df尺寸/结构。

分步操作:

  • 按日期和动物分组,获取中位数,然后选择身高较大的位置(与您的问题相同)
  • .loc在您的df[x]上明确的第一轴索引只是我个人的偏爱。两者都可以很好地按中值高度过滤数据。
  • 对经过高度过滤的数据进行第二次分组比,可以选择在分组比之前或之后的权重。
  • 获取每个动物和日期组的平均值
  • unstack将数据框转换为以动物为第二级的多索引列

仅当groupby.median()支持level参数时,才能避免第二个groupby。但是,由于level不受(大多数还是全部?)groupby方法支持,因此需要第二个groupby。