J'ai remplacé les valeurs manquantes par NaN en utilisant la fonction suivante lambda:
data = data.applymap(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)
, où data est le dataframe sur lequel je travaille.
En utilisant seaborn ensuite, j'ai essayé de tracer un de ses attributs, alcconsumption en utilisant seaborn.distplot comme suit:
seaborn.distplot(data['alcconsumption'],hist=True,bins=100)
plt.xlabel('AlcoholConsumption')
plt.ylabel('Frequency(normalized 0->1)')
Cela me donne l'erreur suivante:
AttributeError: max must be larger than min in range parameter.
Je gérerais certainement les valeurs manquantes avant vous tracez vos données. Le fait de ne pas utiliser dropna()
dépendra entièrement de la nature de votre ensemble de données. alcconsumption
est-il une seule série ou une partie d'une trame de données? Dans ce dernier cas, l'utilisation de dropna()
supprimerait également les lignes correspondantes dans les autres colonnes. Les valeurs manquantes sont-elles rares ou nombreuses? Sont-ils répartis dans votre série ou ont-ils tendance à se produire en groupe? Y a-t-il peut-être des raisons de croire qu'il existe une tendance dans votre ensemble de données?
Si les valeurs manquantes sont peu nombreuses et dispersées, vous pouvez facilement utiliser dropna (). Dans d'autres cas, je choisirais de remplir les valeurs manquantes avec la valeur précédemment observée (1). Ou même remplissez les valeurs manquantes avec des valeurs interpolées (2). Mais fais attention! Le remplacement d'un grand nombre de données par des observations remplies ou interpolées pourrait sérieusement interrompre votre jeu de données et conduire à de très mauvaises conclusions.
Voici quelques exemples d'utilisation de votre extrait ...
seaborn.distplot(data['alcconsumption'],hist=True,bins=100)
plt.xlabel('AlcoholConsumption')
plt.ylabel('Frequency(normalized 0->1)')
... sur un jeu de données synthétique:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
def sample(rows, names):
''' Function to create data sample with random returns
Parameters
==========
rows : number of rows in the dataframe
names: list of names to represent assets
Example
=======
>>> sample(rows = 2, names = ['A', 'B'])
A B
2017-01-01 0.0027 0.0075
2017-01-02 -0.0050 -0.0024
'''
listVars= names
rng = pd.date_range('1/1/2017', periods=rows, freq='D')
df_temp = pd.DataFrame(np.random.randint(-100,100,size=(rows, len(listVars))), columns=listVars)
df_temp = df_temp.set_index(rng)
return df_temp
df = sample(rows = 15, names = ['A', 'B'])
df['A'][8:12] = np.nan
df
Production:
A B
2017-01-01 -63.0 10
2017-01-02 49.0 79
2017-01-03 -55.0 59
2017-01-04 89.0 34
2017-01-05 -13.0 -80
2017-01-06 36.0 90
2017-01-07 -41.0 86
2017-01-08 10.0 -81
2017-01-09 NaN -61
2017-01-10 NaN -80
2017-01-11 NaN -39
2017-01-12 NaN 24
2017-01-13 -73.0 -25
2017-01-14 -40.0 86
2017-01-15 97.0 60
(1) Utilisation du remplissage direct avec pandas.DataFrame.fillna (méthode = ffill)
ffill
"remplira les valeurs vers l'avant", ce qui signifie qu'il remplacera les nan
par la valeur de la ligne ci-dessus.
df = df['A'].fillna(axis=0, method='ffill')
sns.distplot(df, hist=True,bins=5)
plt.xlabel('AlcoholConsumption')
plt.ylabel('Frequency(normalized 0->1)')
(2) Utilisation de l'interpolation avec pandas.DataFrame.interpolate ()
Interpoler les valeurs selon différentes méthodes. L'interpolation temporelle fonctionne sur des données de résolution quotidienne et supérieure pour interpoler une longueur d'intervalle donnée.
df['A'] = df['A'].interpolate(method = 'time')
sns.distplot(df['A'], hist=True,bins=5)
plt.xlabel('AlcoholConsumption')
plt.ylabel('Frequency(normalized 0->1)')
Comme vous pouvez le voir, les différentes méthodes rendent deux résultats très différents. J'espère que cela vous sera utile. Sinon, faites-le moi savoir et j'y reviendrai.
Vous pouvez utiliser la ligne suivante pour sélectionner les valeurs non NaN pour un graphique de distribution utilisant seaborn:
seaborn.distplot(data['alcconsumption'].notnull(),hist=True,bins=100)
C'est un problème connu avec les histogrammes matplotlib/pylab!
Voir par exemple https://github.com/matplotlib/matplotlib/issues/648
où diverses solutions de contournement sont suggérées, deux favoris (par exemple de https://stackoverflow.com/a/19090183/1021819 ) étant:
import numpy as np
nbins=100
A=data['alcconsumption']
Anan=A[~np.isnan(A)] # Remove the NaNs
seaborn.distplot(Anan,hist=True,bins=nbins)
Sinon, spécifiez les bords du bac (dans ce cas en utilisant de toute façon Anan
...):
Amin=min(Anan)
Amax=max(Anan)
seaborn.distplot(A,hist=True,bins=np.linspace(Amin,Amax,nbins))