/ / Pandas Group Зважена середня кількість стовпців - пітон, панди

Середньозважена група Pandas з кількох стовпчиків - python, pandas

Скажімо, у мене є такий кадр даних:

>>> df=pd.DataFrame({"category":["a","a","b","b"],
... "var1":np.random.randint(0,100,4),
... "var2":np.random.randint(0,100,4),
... "weights":np.random.randint(0,10,4)})
>>> df
category  var1  var2  weights
0        a    37    36        7
1        a    47    20        1
2        b    33     7        6
3        b    16     6        8

Я можу обчислити середньозважене значення "var1" як таке:

>>> Grouped=df.groupby("category")
>>> GetWeightAvg=lambda g: np.average(g["var1"], weights=g["weights"])
>>> Grouped.apply(GetWeightAvg)
category
a    38.250000
b    23.285714
dtype: float64

Однак мені цікаво, якщо є спосіб, я можунапишіть мою функцію і застосуйте її до мого об'єднаного об'єкта, таким чином я можу вказати при його застосуванні, який стовпчик я хочу обчислити для (або обох). Замість того, щоб "var1" записано в мою функцію, я хотів би бути в змозі вказати при застосуванні функції.

Так само, як я можу отримати незважену середню кількість обох стовпців:

>>> Grouped[["var1","var2"]].mean()
var1  var2
category
a         42.0  28.0
b         24.5   6.5

Я задаюся питанням, чи є паралельний спосіб зробити це з середньозваженими.

Відповіді:

2 для відповіді № 1

Можна застосувати та повернути обидва середні показники:

In [11]: g.apply(lambda x: pd.Series(np.average(x[["var1", "var2"]], weights=x["weights"], axis=0), ["var1", "var2"]))
Out[11]:
var1       var2
category
a         38.250000  34.000000
b         23.285714   6.428571

Ви можете написати цю дещо чистішу функцію:

In [21]: def weighted(x, cols, w="weights"):
return pd.Series(np.average(x[cols], weights=x[w], axis=0), cols)

In [22]: g.apply(weighted, ["var1", "var2"])
Out[22]:
var1       var2
category
a         38.250000  34.000000
b         23.285714   6.428571

0 для відповіді № 2

Після рішення Енді, я прагнув використати один з рівнів індексу з мульти-індексу, як мої ваги.

np.random.seed(1)
arrays = [list("AAABBB"), [0.01,0.02,0.03,0.07,0.09,0.11]]
tups = list(zip(*arrays))
x = pd.MultiIndex.from_tuples(tups)
df = pd.DataFrame(index=x,data= np.random.randint(10,100,(6,6)),columns = list("STUVWX"))
df.index.names = ["bin","prob"]

S   T   U   V   W   X
bin prob
A   0.0100  47  22  82  19  85  15
0.0200  89  74  26  11  86  81
0.0300  16  35  60  30  28  94
B   0.0700  21  38  39  24  60  78
0.0900  97  97  96  23  19  17
0.1100  73  71  32  67  11  10

Функція адаптації для використання одного з рівнів індексів як ваг.

def weighted(x, w="weights"):
return pd.Series(np.average(x, weights=x.index.get_level_values(w), axis=0),index= x.columns)

і покликання

df.groupby(level=["bin"]).apply(weighted,  "prob")

який дає:

          S       T       U       V       W       X
bin
A   45.5000 45.8333 52.3333 21.8333 56.8333 76.5000
B   67.5185 71.1111 55.1481 41.1852 26.3704 29.9630