J'ai une série chronologique df
qui comporte 2 colonnes. J'essaie de supprimer toutes les listes vides des colonnes annual_cost
tout en prenant une moyenne des listes contenant des flottants pour créer une valeur singulière pour chaque jour individuel. Il y a plusieurs valeurs pour la même date dans la colonne date
et j'essaie donc de fusionner toutes les lignes en fonction de la date. df
ressemble à ceci:
date yearly_cost 0 2009-01-01 435.05 1 2009-01-02 366.11 2 2009-01-03 327.408
Certains jours auront plusieurs listes et donc je dois prendre une moyenne sur les deux listes pour créer une seule valeur.
J'ai essayé d'utiliser .dropna ()
, np.nanmean ()
et de faire la moyenne des listes avec ts.yearly_cost = [np.mean (i ) if isinstance (i, list) else i for i in ts.yearly_cost]
avec concaténation par date
avec .set_index ('date'). mean (axis = 1) .reset_index (name = 'Yearly_Cost')
qui a travaillé pour des séries chronologiques dans le passé sans listes vides.
Je souhaite que le résultat final se présente comme tel:
date yearly_cost 0 2009-01-01 [] 1 2009-01-02 [409.45,294.33,394.56] 2 2009-01-03 [403.45,175.30,323.67] 3 2009-01-01 [456.34,355.3,493.5] 4 2009-01-02 [] 5 2009-01-03 [295.39, 439.23]
Toute aide à ce sujet serait grandement appréciée. Merci
3 Réponses :
S'il y a des listes dans la colonne annual_cost
, aplatissez-les d'abord, puis agrégez mean
:
s = pd.DataFrame(df['yearly_cost'].values.tolist(), index=df['date']).stack() df = s.mean(level=0).reset_index(name='yearly_cost') print (df) date yearly_cost 0 2009-01-02 366.113333 1 2009-01-03 327.408000 2 2009-01-01 435.046667
Une autre solution:
import ast #necessary if string repr of lists #df['yearly_cost'] = df['yearly_cost'].apply(ast.literal_eval) from itertools import chain df = pd.DataFrame({ 'yearly_cost' : list(chain.from_iterable(df['yearly_cost'].tolist())), 'date' : df['date'].values.repeat(df['yearly_cost'].str.len()) }) df = df.groupby('date', as_index=False)['yearly_cost'].mean() print (df) date yearly_cost 0 2009-01-01 435.046667 1 2009-01-02 366.113333 2 2009-01-03 327.408000
Je reçois l'erreur suivante à la première étape TypeError: impossible de réduire avec le type flexible
Un autre problème est que la troisième date a la somme de deux moyennes plutôt que d'une seule moyenne de la journée entière.
@ geds133 - oui, la solution a donc changé
Je viens de recevoir MemoryError:
@ geds133 Quelle est la taille de vos données?
@piRSquared seulement 300 000 lignes
IIUC
Supprimez la liste vide en convertissant le type en booléen.
df.groupby('date')['yearly_cost'].apply(lambda x : np.mean(x.sum()))
Après avoir supprimé la liste vide, vous pouvez faire groupby
df=df[df.yearly_cost.astype(bool)].copy()
Recevez la même erreur que ci-dessus TypeError: impossible de réduire avec le type flexible
@ geds133 vous devez nous indiquer si la colonne 'annual_cost'
est constituée de chaînes ou de listes.
@piRSquared Listes vides et listes avec des flottants
groupby.sum
et np.mean
La somme concaténera les listes.
i, u = df.date.factorize() j = i.repeat([*map(len, df.yearly_cost)]) v = np.concatenate(df.yearly_cost) c = np.bincount(j) s = np.bincount(j, v) pd.Series(s / c, u) 2009-01-01 435.046667 2009-01-02 366.113333 2009-01-03 327.408000 dtype: float64
Si ce sont des chaînes
df.groupby('date').yearly_cost.apply(lambda x: np.concatenate([*x]).mean())
from ast import literal_eval df.yearly_cost.apply(literal_eval).groupby(df.date).sum().apply(np.mean)
df.groupby('date').yearly_cost.sum().apply(np.mean) date 2009-01-01 435.046667 2009-01-02 366.113333 2009-01-03 327.408000 Name: yearly_cost, dtype: float64
J'ai parlé trop tôt, il semble toujours y avoir des listes vides dans la série chronologique, car lorsque j'essaie de créer une moyenne mobile, j'obtiens cette erreur ValueError: impossible de convertir la chaîne en flottant: '[]'
@ geds133 J'obtiens ça quand je fais float ('[]')
ce qui signifie que vous avez des chaînes dans vos données qui sont contraires à ce que vous avez affirmé. Cela signifie que vous avez de mauvaises données et que vous devez les nettoyer. Plusieurs utilisateurs ont suggéré literal_eval
. Avant d'utiliser l'une des techniques, essayez de faire ceci df ['year_cost'] = df ['annual_cost']. Astype (str) .apply (literal_eval)
. Assurez-vous de depuis ast import literal_eval
Est-il possible que les listes vides soient comptées comme des chaînes? Le df
renvoyé est une série avec date
comme index et pas de annual_cost
.
quelques questions: pourquoi vos coûts annuels sont-ils associés aux jours? pourquoi stockez-vous des listes dans des éléments de bloc de données? dataframe fonctionne beaucoup mieux avec des scalaires dans chaque ligne / colonne