[英]Mean of last N rows of pandas dataframe if the previous rows meet a condition
[英]Conditional mean and sum of previous N rows in pandas dataframe
關注的是這個示范性的熊貓數據幀:
Measurement Trigger Valid
0 2.0 False True
1 4.0 False True
2 3.0 False True
3 0.0 True False
4 100.0 False True
5 3.0 False True
6 2.0 False True
7 1.0 True True
每當Trigger
為True
,我希望計算最后3個(從當前開始)有效測量的總和和平均值。 如果Valid
True
,則測量被認為是有效的。 那么讓我們使用上面數據框中的兩個例子來澄清:
Index 3
:應使用指數2,1,0
。 預期Sum = 9.0, Mean = 3.0
Index 7
:應使用指數7,6,5
。 預期Sum = 6.0, Mean = 2.0
我嘗試過pandas.rolling
並創建新的移位列,但沒有成功。 請參閱我的測試中的以下摘錄(應該直接運行):
import unittest
import pandas as pd
import numpy as np
from pandas.util.testing import assert_series_equal
def create_sample_dataframe_2():
df = pd.DataFrame(
{"Measurement" : [2.0, 4.0, 3.0, 0.0, 100.0, 3.0, 2.0, 1.0 ],
"Valid" : [True, True, True, False, True, True, True, True],
"Trigger" : [False, False, False, True, False, False, False, True],
})
return df
def expected_result():
return pd.DataFrame({"Sum" : [np.nan, np.nan, np.nan, 9.0, np.nan, np.nan, np.nan, 6.0],
"Mean" :[np.nan, np.nan, np.nan, 3.0, np.nan, np.nan, np.nan, 2.0]})
class Data_Preparation_Functions(unittest.TestCase):
def test_backsummation(self):
N_SUMMANDS = 3
temp_vars = []
df = create_sample_dataframe_2()
for i in range(0,N_SUMMANDS):
temp_var = "M_{0}".format(i)
df[temp_var] = df["Measurement"].shift(i)
temp_vars.append(temp_var)
df["Sum"] = df[temp_vars].sum(axis=1)
df["Mean"] = df[temp_vars].mean(axis=1)
df.loc[(df["Trigger"]==False), "Sum"] = np.nan
df.loc[(df["Trigger"]==False), "Mean"] = np.nan
assert_series_equal(expected_result()["Sum"],df["Sum"])
assert_series_equal(expected_result()["Mean"],df["Mean"])
def test_rolling(self):
df = create_sample_dataframe_2()
df["Sum"] = df[(df["Valid"] == True)]["Measurement"].rolling(window=3).sum()
df["Mean"] = df[(df["Valid"] == True)]["Measurement"].rolling(window=3).mean()
df.loc[(df["Trigger"]==False), "Sum"] = np.nan
df.loc[(df["Trigger"]==False), "Mean"] = np.nan
assert_series_equal(expected_result()["Sum"],df["Sum"])
assert_series_equal(expected_result()["Mean"],df["Mean"])
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(Data_Preparation_Functions)
unittest.TextTestRunner(verbosity=2).run(suite)
非常感謝任何幫助或解決方案。 謝謝,干杯!
編輯:澄清:這是我期望的結果數據幀:
Measurement Trigger Valid Sum Mean
0 2.0 False True NaN NaN
1 4.0 False True NaN NaN
2 3.0 False True NaN NaN
3 0.0 True False 9.0 3.0
4 100.0 False True NaN NaN
5 3.0 False True NaN NaN
6 2.0 False True NaN NaN
7 1.0 True True 6.0 2.0
編輯2:另一個澄清:
我確實沒有計算錯誤,而是我沒有盡可能明確地表達我的意圖。 這是使用相同數據幀的另一個嘗試:
讓我們首先看一下Trigger
列:我們在索引3(綠色矩形)中找到第一個True
。 所以索引3是我們開始尋找的點。 索引3處沒有有效測量值(Column Valid
為False
;紅色矩形)。 所以,我們開始回到過去,直到我們累積了三行,其中Valid
是True
。 對於索引2,1和0,會發生這種情況。對於這三個索引,我們計算列Measurement
(藍色矩形)的總和和平均值:
現在我們開始這個小算法的下一次迭代:再次查看Trigger
列中的下一個True
。 我們在索引7(綠色矩形)找到它。 在索引7處還有一個有效的度量標准,所以我們這次包括它。 對於我們的計算,我們使用索引7,6和5(綠色矩形),從而得到:
我希望,這會對這個小問題有所了解。
繼承人選擇,采取3期滾動均值和總和
df['RollM'] = df.Measurement.rolling(window=3,min_periods=0).mean()
df['RollS'] = df.Measurement.rolling(window=3,min_periods=0).sum()
現在設置False Triggers等於NaN
df.loc[df.Trigger == False,['RollS','RollM']] = np.nan
產量
Measurement Trigger Valid RollM RollS
0 2.0 False True NaN NaN
1 4.0 False True NaN NaN
2 3.0 False True NaN NaN
3 0.0 True False 2.333333 7.0
4 100.0 False True NaN NaN
5 3.0 False True NaN NaN
6 2.0 False True NaN NaN
7 1.0 True True 2.000000 6.0
編輯,更新以反映有效參數
df['mean'],df['sum'] = np.nan,np.nan
roller = df.Measurement.rolling(window=3,min_periods=0).agg(['mean','sum'])
df.loc[(df.Trigger == True) & (df.Valid == True),['mean','sum']] = roller
df.loc[(df.Trigger == True) & (df.Valid == False),['mean','sum']] = roller.shift(1)
產量
Measurement Trigger Valid mean sum
0 2.0 False True NaN NaN
1 4.0 False True NaN NaN
2 3.0 False True NaN NaN
3 0.0 True False 3.0 9.0
4 100.0 False True NaN NaN
5 3.0 False True NaN NaN
6 2.0 False True NaN NaN
7 1.0 True True 2.0 6.0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.