Фрейм данных Pandas: среднее значение значений столбца B в столбце A windows

#python #pandas #dataframe #mean #binning

#python #pandas #фрейм данных #среднее #привязка

Вопрос:

Если у меня есть фрейм данных pandas в Python, такой как:

 import numpy as np
import pandas as pd

a = np.random.uniform(0,10,20)
b = np.random.uniform(0,1,20)
data = np.vstack([a,b]).T

df = pd.DataFrame(data)
df.columns = ['A','B']
df.sort_values(by=['A'])

           A         B
5   0.057519  0.465408
14  1.610972  0.398077
3   1.725556  0.397708
17  1.734124  0.600723
11  1.944105  0.694152
19  3.265799  0.878538
13  3.352460  0.770505
10  3.865299  0.064723
16  4.137863  0.659662
12  5.597172  0.122269
7   5.990105  0.667533
6   6.410582  0.193027
9   6.881429  0.041691
15  7.522877  0.268144
1   8.093155  0.130559
0   8.699004  0.996624
8   8.755095  0.495984
4   9.135271  0.792966
18  9.440045  0.477514
2   9.654226  0.509812
  

Возможно ли эффективно вычислить среднее значение B значений столбца в интервалах столбца A ?

Например, может потребоваться вычислить среднее значение значений в столбце, B которые попадают в диапазоны ячеек [0,1,2,3,4,5,6,7,8,9,10] столбца A . Таким образом, для диапазона ячеек A = {0-1} среднее значение B значений, попадающих в эту ячейку, будет 0.465408 , для диапазона ячеек A = {1-2} среднее значение значений B, попадающих в эту ячейку, будет 0.522665 и т.д.

Я нашел pandas.core.window.Rolling.mean (см. https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.core.window .Rolling.mean.html ) но, похоже, он вычисляет средние значения по окну указанной длины, а не по ширине ячейки другого столбца.

Ответ №1:

Использование cut для сегментации A столбца на ячейки, а затем применение groupby к этим сегментам и вычисление mean значения B :

 df.groupby(pd.cut(df['A'], bins=np.arange(11)))['B'].mean()
  

Вывод:

 A
(0, 1]     0.465408
(1, 2]     0.522665
(2, 3]          NaN
(3, 4]     0.571255
(4, 5]     0.659662
(5, 6]     0.394901
(6, 7]     0.117359
(7, 8]     0.268144
(8, 9]     0.541056
(9, 10]    0.593431
  

Обновление: вы можете использовать agg для применения набора различных функций агрегирования, таких как mean , std и size , например:

 df.groupby(pd.cut(df['A'], bins=np.arange(11)))['B'].agg(['mean', 'std', 'size'])
  

Вывод:

              mean       std  size
A                                
(0, 1]   0.465408       NaN     1
(1, 2]   0.522665  0.149038     4
(2, 3]        NaN       NaN     0
(3, 4]   0.571255  0.441983     3
(4, 5]   0.659662       NaN     1
(5, 6]   0.394901  0.385560     2
(6, 7]   0.117359  0.107011     2
(7, 8]   0.268144       NaN     1
(8, 9]   0.541056  0.434788     3
(9, 10]  0.593431  0.173556     3
  

Комментарии:

1. Есть ли способ также возвращать количество значений в каждом интервале в виде отдельного столбца? Таким образом, можно использовать .std() вместо .mean() , а затем разделить на количество выборок, чтобы получить ошибку в среднем значении в каждой ячейке.

2. Большое спасибо, очень элегантное решение!

3. Конечно, просто добавьте ‘median’ в agg список параметров, например .agg(['mean', 'std', 'size', 'median'])

4. А для вычисления средних значений индексов вы можете использовать pd.IntervalIndex(df.index)

Ответ №2:

Вы могли бы сделать что-то вроде этого:

 import numpy as np
import pandas as pd

a = np.random.uniform(0,10,20)
b = np.random.uniform(0,1,20)
data = np.vstack([a,b]).T

df = pd.DataFrame(data=data, columns=['A', 'B'])

bins = pd.cut(df['A'], bins=10)
df.groupby(bins)['B'].agg({'B': 'mean'}).reset_index()
  

Вы также можете предоставить список ячеек для pd.cut , например bins=[0,1,2,3,4,5,6,7,8,9,10] .