Disons que j'ai le bloc de données suivant:
>>> df a 2019-04-05 00:00:00 2.0 2019-04-05 00:00:08 3.0 2019-04-05 00:00:20 4.0 2019-04-05 00:00:28 4.0
Je voudrais avoir 1 valeur toutes les 7 secondes (en supposant qu'il y ait une valeur, sinon juste un NaN), donc un dataframe qui ressemble à ce qui suit:
>>> df a 2019-04-05 00:00:00 2.0 2019-04-05 00:00:01 NaN 2019-04-05 00:00:02 NaN 2019-04-05 00:00:03 NaN 2019-04-05 00:00:04 NaN 2019-04-05 00:00:05 NaN 2019-04-05 00:00:06 NaN 2019-04-05 00:00:07 NaN 2019-04-05 00:00:08 3.0 2019-04-05 00:00:09 NaN 2019-04-05 00:00:10 NaN 2019-04-05 00:00:11 NaN 2019-04-05 00:00:12 NaN 2019-04-05 00:00:13 NaN 2019-04-05 00:00:14 NaN 2019-04-05 00:00:15 NaN 2019-04-05 00:00:16 NaN 2019-04-05 00:00:17 NaN 2019-04-05 00:00:18 NaN 2019-04-05 00:00:19 NaN 2019-04-05 00:00:20 4.0 2019-04-05 00:00:21 NaN 2019-04-05 00:00:22 NaN 2019-04-05 00:00:23 NaN 2019-04-05 00:00:24 NaN 2019-04-05 00:00:25 NaN 2019-04-05 00:00:26 NaN 2019-04-05 00:00:27 NaN 2019-04-05 00:00:28 4.0 2019-04-05 00:00:29 NaN 2019-04-05 00:00:30 NaN 2019-04-05 00:00:31 NaN
Le point de 7 secondes est arbitraire, je prendrais en fait des valeurs à peu près toutes les minutes. Voici ce que j'ai essayé jusqu'à présent:
a 2019-04-05 00:00:00 2.0 2019-04-05 00:00:07 3.0 2019-04-05 00:00:14 4.0 2019-04-05 00:00:21 5.0 2019-04-05 00:00:28 4.0
mais cela produit le dataframe suivant à la place:
a 2019-04-05 00:00:00 2.0 2019-04-05 00:00:07 3.0 2019-04-05 00:00:14 4.0 2019-04-05 00:00:21 5.0 2019-04-05 00:00:28 4.0
Remarque: I Je ne suis pas gêné par le manque de NaN
entre ces points, car ils sont sous-entendus. Je ne suis tout simplement pas satisfait du timing, car il force une valeur toutes les 7 secondes, alors que je veux simplement interdire aux valeurs d'être à moins de 7 secondes l'une de l'autre, pas besoin d'une valeur toutes les 7 secondes.
Edith pour plus de clarté:
DATAFRAME I Don't WANT:
df = df.resample('7s').first()
DATAFRAME I DO WANT:
>>> df a 2019-04-05 00:00:00 2.0 2019-04-05 00:00:01 NaN 2019-04-05 00:00:02 NaN 2019-04-05 00:00:03 NaN 2019-04-05 00:00:04 NaN 2019-04-05 00:00:05 NaN 2019-04-05 00:00:06 NaN 2019-04-05 00:00:07 NaN 2019-04-05 00:00:08 3.0 2019-04-05 00:00:09 NaN 2019-04-05 00:00:10 NaN 2019-04-05 00:00:11 NaN 2019-04-05 00:00:12 NaN 2019-04-05 00:00:13 NaN 2019-04-05 00:00:14 NaN 2019-04-05 00:00:15 NaN 2019-04-05 00:00:16 NaN 2019-04-05 00:00:17 NaN 2019-04-05 00:00:18 NaN 2019-04-05 00:00:19 NaN 2019-04-05 00:00:20 4.0 2019-04-05 00:00:21 NaN 2019-04-05 00:00:22 NaN 2019-04-05 00:00:23 NaN 2019-04-05 00:00:24 NaN 2019-04-05 00:00:25 NaN 2019-04-05 00:00:26 NaN 2019-04-05 00:00:27 NaN 2019-04-05 00:00:28 4.0 2019-04-05 00:00:29 NaN 2019-04-05 00:00:30 NaN 2019-04-05 00:00:31 NaN
4 Réponses :
Vous pouvez suréchantillonner votre dataframe, vous étiez très proche;
df = df.resample('7s').first() df = df.resample(rule='1s')
Cela créera une dataframe avec NaN pour les lignes nouvellement insérées sur les secondes ajoutées.
p >
Cela ne produit pas de dataframe pour moi, cela transforme simplement df
en un DatetimeIndexResampler [freq =
Cela n'utilise pas strictement les méthodes pandas, mais cela fait le travail.
c = [dt.datetime(1,1,1) for i in range(df.shape[1])] for index, row in df.iterrows(): for i in range(len(c)): if index.to_pydatetime() - c[i] > dt.timedelta(seconds=x) and not(np.isnan(row[i])): c[i] = index.to_pydatetime() else: row[i] = np.nan
une fois appliqué à df
, retournera le dataframe souhaité. p >
Modifier:
Pour un dataframe de n
colonnes, et une valeur toutes les x
lignes:
c = [x+1 for i in range(df.shape[1])] for index, row in df.iterrows(): c = [i+1 for i in c] for i in range(len(c)): if c[i] > x and not(np.isnan(row[i])): c[i] = 0 else: row[i] = np.nan
Qu'en est-il du remplissage des valeurs NA avant le rééchantillonnage?
a 2019-04-05 00:00:00 2 2019-04-05 00:00:07 something 2019-04-05 00:00:14 something 2019-04-05 00:00:21 5 2019-04-05 00:00:28 4
Ensuite, les valeurs ne seront pas forcées:
df = df.fillna('something').resample('7s').first()
Notez que si vous remplissez le NA avec une chaîne comme quelque chose
, cela convertira la colonne entière en objet
au lieu de float
. Donc, si vous souhaitez conserver le type de données, vous pouvez utiliser df.fillna (0)
à la place
qui oblige toujours les valeurs à être alignées sur chaque marque de 7 secondes, je veux juste qu'il n'y ait pas 2 valeurs à moins de 7 secondes l'une de l'autre.
def f(): skip = 0 for row in df.itertuples(): if skip == 0: if pd.notna(row.a): yield row skip = 7 else: skip = skip - 1 pd.DataFrame(f())
Cela produit le dataframe que j'ai dit que je ne voulais pas modifier: dataframe **
Qu'entendez-vous par base de données
?
Je voulais dire dataframe, désolé
Modifié la réponse. Vérifier. La seule différence avec votre sortie attendue est dans 00:00:20. Pourquoi 00:00:20 NaN est-il dans votre sortie attendue?
voulez-vous dire 00:00:21? 00:00:20 est 4.0
Oui. Je voulais dire 00:00:21.
C'est parce que je ne veux une valeur que toutes les 7 secondes. Donc à 00:00:19
la valeur la plus récente vue est 3.0
à 00:00:08
, donc quand elle atteint 00 : 00: 20
la valeur la plus proche est à plus de 7 secondes (en regardant uniquement en arrière). À 00:00:21
, la valeur la plus proche est à seulement 1, donc 5.0
est défini sur NaN
Je l'ai. Plus tôt, je pensais que vous vouliez garder la première valeur dans chaque groupe de 7s. Vérifiez la nouvelle solution.
Je viens d'essayer cela, et cela a semblé fonctionner pour toutes les valeurs à l'exception du 4.0 à 00:00:28
Rééchantillonnez le résultat à la fréquence d'origine.