Préoccupés est cette exemplaire pandas géants dataframe:moyenne conditionnelle et la somme des lignes précédentes N en pandas géants 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
Chaque fois que Trigger
est True
, je souhaite calculer la somme et la moyenne des 3 dernières (à partir de courant) valide des mesures. Les mesures sont considérées comme valides si la colonne Valid
est True
. Donc, clarifions en utilisant les deux exemples ci-dessus dans la trame de données:
Index 3
: Indices2,1,0
devraient être utilisés.Sum = 9.0, Mean = 3.0
Index 7
: Les index7,6,5
doivent être utilisés. ExpectedSum = 6.0, Mean = 2.0
J'ai essayé pandas.rolling
et la création de nouvelles, déplacé des colonnes, mais n'a pas réussi. Voir l'extrait suivant de mes tests (qui devraient directement fonctionner):
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)
Toute aide ou solution est grandement appréciée. Merci et à bientôt!
EDIT: Précision: Ceci est la trame de données résultante je me attends:
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: Une autre précision:
Je ne en effet pas mésestimer, mais je ne l'ai pas fait mes intentions aussi clairement que je Pourrais avoir. Voici un autre essai en utilisant la même dataframe:
Examinons d'abord la colonne Trigger
: Nous trouvons le premier True
indice 3 (rectangle vert). Donc, l'index 3 est le point où nous commençons à chercher. Il n'y a pas de mesure valide à l'index 3 (la colonne Valid
est False
, rectangle rouge). Ainsi, nous commençons à aller plus loin dans le temps, jusqu'à ce que nous ayons accumulé trois lignes, où Valid
est True
. Cela se produit pour les indices 2,1 et 0. Pour ces trois indices, on calcule la somme et la moyenne de la colonne Measurement
(rectangle bleu):
- SUM: 2,0 + 4,0 + 3,0 = 9,0
- MEAN: (2,0 + 4,0 + 3,0)/3 = 3,0
maintenant, nous commençons la prochaine itération de ce petit algorithme: Regardez à nouveau pour la prochaine True
dans la colonne Trigger
. Nous le trouvons à l'index 7 (rectangle vert). Il y a aussi un mesuremnt valide à l'index 7, donc nous l'incluons cette fois. Pour notre calcul, nous utilisons les indices 7,6 et 5 (rectangle vert), et ainsi obtenir:
- SUM: 1,0 + 2,0 + 3,0 = 6,0
- MEAN: (1,0 + 2,0 + 3,0)/3 = 2.0
J'espère que cela éclaircira davantage ce petit problème.
J'ai vu une question comme celui-ci, est essentiellement à détecter la cumsum, je vais maintenant trouver dehors! – ileadall42