簡體   English   中英

pandas數據幀中前N行的條件均值和總和

[英]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

每當TriggerTrue ,我希望計算最后3個(從當前開始)有效測量的總和和平均值。 如果Valid True ,則測量被認為是有效的。 那么讓我們使用上面數據框中的兩個例子來澄清:

  1. Index 3 :應使用指數2,1,0 預期Sum = 9.0, Mean = 3.0
  2. 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 ValidFalse ;紅色矩形)。 所以,我們開始回到過去,直到我們累積了三行,其中ValidTrue 對於索引2,1和0,會發生這種情況。對於這三個索引,我們計算列Measurement (藍色矩形)的總和和平均值:

  • SUM:2.0 + 4.0 + 3.0 = 9.0
  • MEAN:(2.0 + 4.0 + 3.0)/ 3 = 3.0

現在我們開始這個小算法的下一次迭代:再次查看Trigger列中的下一個True 我們在索引7(綠色矩形)找到它。 在索引7處還有一個有效的度量標准,所以我們這次包括它。 對於我們的計算,我們使用索引7,6和5(綠色矩形),從而得到:

  • SUM:1.0 + 2.0 + 3.0 = 6.0
  • 意思是:(1.0 + 2.0 + 3.0)/ 3 = 2.0

我希望,這會對這個小問題有所了解。

繼承人選擇,采取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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM