【问题标题】:How to add intervals into the grouping result如何将间隔添加到分组结果中
【发布时间】:2017-05-08 05:02:51
【问题描述】:

我需要按yearplaceprice 的间隔对数据进行分组(步长为5)。对于每个组我想估计中位数level

df = 
year   place   price   level
1994   AAA     90      1
1993   BBB     89      1
1994   AAA     91      2
1998   AAA     92      3
1990   BBB     80      0
1994   AAA     90      1
1990   BBB     81      0
1991   BBB     92      1

我可以对数据进行分组并计算level的中值,但是我不知道如何添加price的区间:

grouped_df = df.groupby(["year","place"]).agg({'level':'median'}).reset_index()

正确的grouped_df结构如下(数字可能不同,只是数据结构的一个例子):

grouped_df = 

year   place   price_min   price_max   level
1990   AAA     80          85          1
...

更新:

最终结果应该是这样的。所以,基本上price_minprice_max 分别是上下界:

   year_ place_  level_median price_min price_max
0   1990    BBB             0  75       80
1   1991    BBB             1  80       85
2   1993    BBB             1  85       90
3   1994    AAA             1  85       90
4   1998    AAA             3  90       95

【问题讨论】:

  • df2 = df.groupby(["year","place"]).agg({'level':'median','price':[np.min, np.max]}).reset_index()?

标签: python pandas


【解决方案1】:

我认为你需要aggregate + cut

但如果相同的输出需要其他类别 - 添加5。不理想,但列已转换为 int 并添加了 mask 5 然后转换为 categorical 回来。

bins = range(0, df['price'].max() + 5, 5)
labels_low = range(0, df['price'].max(), 5)

df2['price_min'] = pd.cut(df2['price_min'], bins=bins, labels=labels_low)
df2['price_max'] = pd.cut(df2['price_max'], bins=bins, labels=labels_low).astype(int)
mask = df2['price_min'] == df2['price_max']
df2['price_max'] = df2['price_max'].mask(mask, df2['price_max'] + 5).astype('category')

print (df2)
   year_ place_  level_median  price_min  price_max
0   1990    BBB             0         75         80
1   1991    BBB             1         90         95
2   1993    BBB             1         85         90
3   1994    AAA             1         85         90
4   1998    AAA             3         90         95

没有categorical的解决方案:

df2['price_min'] = pd.cut(df2['price_min'], bins=bins, labels=labels_low).astype(int)
df2['price_max'] = pd.cut(df2['price_max'], bins=bins, labels=labels_low).astype(int)
mask = df2['price_min'] == df2['price_max']
df2['price_max'] = df2['price_max'].mask(mask, df2['price_max'] + 5)
print (df2)
   year_ place_  level_median  price_min  price_max
0   1990    BBB             0         75         80
1   1991    BBB             1         90         95
2   1993    BBB             1         85         90
3   1994    AAA             1         85         90
4   1998    AAA             3         90         95

【讨论】:

  • 可能我没有解释清楚,但是我在问题中写到,区间中的步长应该是5。所以,应该是(80-85], (85-90],( 90-95]。当然它不应该是硬编码的。
  • 谢谢。 price_min 和 price_max 是每个区间的下限和上限。所以,基本上最终的结果和这个很相似,只是 price_min 和 price_max 应该是数字。
  • minprice_min有什么区别?
  • 第二行price_minprice_max 都等于90,而min1max1 等于92。我不确定我是否理解这一点。
  • 嗯,为什么在第二低 92 是您的问题 80 85 中的间隔?
【解决方案2】:

我认为,如果您希望将价格分组在 5 范围内,我会使用 pd.cut 创建范围,然后使用 groupby。

df.groupby(['year','place',pd.cut(df.price,[79,86,91,96,101],labels=['80-85','86-90','91-95','96-100'])]).agg({'price':['min','max'],'level':'median'})

输出:

                 price      level
                   min max median
year place price                 
1990 BBB   80-85    80  81      0
1991 BBB   91-95    92  92      1
1993 BBB   86-90    89  89      1
1994 AAA   86-90    90  91      1
1998 AAA   91-95    92  92      3

让我们试试这个:

df2 = df.groupby(['year',
                  'place',
                   pd.cut(df.price,[i for i in range(np.min(df.price)-5,np.max(df.price)+5,5)])]
                ).agg({'price':['min','max'],'level':'median'})

【讨论】:

  • 有没有办法让它自动化?在我的真实数据中,我有很多区间。
  • 最小和最大期望值?
  • 什么意思? price_min 是区间的下限,price_max 是区间的上限。因此,有两列与价格相关。
  • @ScottBoston 很好的答案,我用你的答案来扩展我的答案,所以我删除了它。否则就不公平了!我在末尾添加了.reset_index().sort_values([('price','min price')]) 以按升序排列。只是想我会把它留给 OP 以防他们需要它。祝你有愉快的一天:)
猜你喜欢
  • 2022-01-18
  • 1970-01-01
  • 2022-10-17
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 2014-10-19
  • 1970-01-01
  • 2017-12-27
相关资源
最近更新 更多