2017-10-13 69 views
2

關注前N行的總和是該示例性大熊貓數據幀:條件均值在大熊貓數據幀

 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(從電流開始)的平均有效測量。如果列ValidTrue,則測量被認爲是有效的。因此,讓我們澄清在使用上述數據幀的兩個例子:

  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 

EDIT2:另一個澄清:

我確實沒有算錯,而是我沒有讓我的意圖,我清晰可以有。下面是使用相同的數據幀的另一個嘗試:

Desired dataframe, relevant fields highlighted

讓我們在Trigger列先來看一下:我們發現在指數3(綠色矩形)第一True。所以索引3是我們開始尋找的地方。在索引3處沒有有效的測量(列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
  • MEAN:(1.0 + 2.0 + 3.0)/ 3 = 2.0

我希望這可以讓我們更多地瞭解這個小問題。

+0

我已經看到這樣的問題,主要是檢測cumsum,我現在去尋找吧! – ileadall42

回答

1

這裏有一個選項,採取3期滾動平均值,總結

df['RollM'] = df.Measurement.rolling(window=3,min_periods=0).mean() 

df['RollS'] = df.Measurement.rolling(window=3,min_periods=0).sum() 

現在設置虛假觸發等於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 
+0

這不是我正在尋找的。爲了澄清,我將表格形式的預期結果添加到原始文章中。 – bolla

+0

你能進一步解釋這是不正確的嗎?它與您的樣本相匹配,除了索引三中的數字外,我相信您錯過了計算它們的時間,並且做了前三個,不包括當前值@bolla – DJK

+0

請參閱我的原始文章中的第二次編輯。 – bolla