1
votes

Ajout de mois manquants à un dataframe avec des valeurs nulles

J'ai un DataFrame avec lequel j'essaie de trouver la fréquence de certains événements. Ainsi, par exemple, il est répertorié comme suit

Month Year Event Count of Events
1     2018 A     02
1     2018 B     00
1     2018 C     00
2     2018 A     00
2     2018 B     00
2     2018 B     01
...

etc. J'ai tout regroupé par fréquence d'événement par an. Je l'ai fait en utilisant le code suivant.

Cela compte tous les événements pour que je puisse les faire la moyenne

df.groupby(['Event'])['Count of Events'].mean()

Ce qui nous donne quelque chose du genre

Year Month Event Count of Events
2018 01    A     2
2018 02    B     1
...

Et puis j'obtiens la moyenne de la fréquence à laquelle cela se produit par mois pendant toute l'année en utilisant

df.groupby(['Year','Month','Event'])['Event'].size().rename('Count of Events').reset_index()

Ce qui me donne la moyenne. Cependant, une chose que j'ai remarquée est que j'ai peut-être des lacunes. Par exemple, l'événement «A» peut se produire en janvier et en février, mais pas en mars, donc cela ne me donnera pas une véritable «moyenne» sur l'année. Quelle serait la meilleure façon de «boucher» ces trous? Par exemple, dans la liste d'exemples ci-dessus,

Month Year Event UniqueID
1     2018 A     01
1     2018 A     02
2     2018 B     03
....

serait le résultat final optimal avant de faire la moyenne. Merci!


0 commentaires

3 Réponses :


0
votes

Je pense que vous avez besoin de fillna: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html

C'est un moyen très simple de remplir des valeurs nulles et de désigner avec quoi les remplir.


1 commentaires

Je pense que le problème est que certaines combinaisons des colonnes groupby ( Year, Month ) n'apparaissent tout simplement pas dans le DataFrame d'origine, de sorte que le DataFrame résultant manque de lignes entières - - il n'y a aucune valeur np.nan à remplir.



3
votes

Vous étiez proche de la solution. Après le regroupement, décompressez le dataframe dans un formulaire "large" (de cette façon, vous aurez chaque combinaison d'un mois et d'un an), remplissez les valeurs manquantes avec des 0 et empilez-les:

df.groupby(["Month", "Year", "Event"]).size().unstack().fillna(0).stack()
#Month  Year  Event
#1      2018  A        2.0
#             B        0.0
#2      2018  A        0.0
#             B        1.0

p>


1 commentaires

Impressionnant! Merci beaucoup! Existe-t-il un moyen simple de conserver la 4ème colonne (Le décompte "dérivé" de la colonne nommée de cette façon sans utiliser .rename?



1
votes

La solution proposée par DYZ ne produit des données que pour les mois "présents".

Mais considérez les données source comme ceci:

       Count of Events
Event                 
A             0.714286
B             0.428571

où il n'y a pas de données pour mars, mai et juin, donc le résultat est imprimé selon DYZ aura des "lacunes".

Notez également qu'un tel détail concernant les "lacunes" est la source des données:

  • Pour certains types d'événements, vous pouvez avoir des données "absentes" également pour le premier et / ou dernier mois.
  • Mais néanmoins, du moins à mon avis, la vraie moyenne devrait être calculée comme une somme d'événements d'un type particulier, divisée par le nombre de mois l'ensemble de l'activité , et non la durée de plusieurs mois de l'activité en cours .

Par exemple dans mon échantillon de données, si le premier événement a eu lieu en janvier et le dernier en juillet, quel que soit le type d'événement , toute l'activité a pris 7 mois.

L'une des étapes devrait donc être de calculer MonthNo code > - le nombre de mois de toute activité.

Une autre proposition consiste à "passer" de colonnes distinctes Année / Mois à Dat (DateTime) et définissez-le comme index. Cette colonne (en fait l'index) sera nécessaire à un moment donné (voir ci-dessous).

Donc ma proposition pour écrire le script est:

df3.groupby(level=0).sum() / MonthNo

Ensuite, si vous voulez avoir des lignes avec zéro nombre d'événements pour les mois "d'interruption", appel rééchantillonner pour chaque type d'événement (ici l'index DateTime est nécessaire):

                  Count of Events
Event Dat                        
A     2018-01-01                2
      2018-02-01                0
      2018-03-01                0
      2018-04-01                2
      2018-05-01                0
      2018-06-01                0
      2018-07-01                1
B     2018-02-01                1
      2018-03-01                0
      2018-04-01                0
      2018-05-01                0
      2018-06-01                0
      2018-07-01                2

Le résultat est:

df3 = df2.groupby(['Event']).resample('MS').sum()


0 commentaires