web-dev-qa-db-fra.com

Formatez certaines colonnes de données flottantes en pourcentage dans pandas

J'essaie d'écrire un papier dans le cahier IPython, mais j'ai rencontré quelques problèmes avec le format d'affichage. Disons que j'ai la structure de données suivante df, existe-t-il un moyen de formater var1 et var2 en décimales à 2 chiffres et var3 en pourcentages.

       var1        var2         var3    
id                                              
0    1.458315    1.500092   -0.005709   
1    1.576704    1.608445   -0.005122    
2    1.629253    1.652577   -0.004754    
3    1.669331    1.685456   -0.003525   
4    1.705139    1.712096   -0.003134   
5    1.740447    1.741961   -0.001223   
6    1.775980    1.770801   -0.001723    
7    1.812037    1.799327   -0.002013    
8    1.853130    1.822982   -0.001396    
9    1.943985    1.868401    0.005732

Les nombres à l'intérieur ne sont pas multipliés par 100, par ex. -0,0057 = -0,57%.

47
user3576212

remplacez les valeurs à l'aide de la fonction round et formatez la représentation sous forme de chaîne des nombres en pourcentage:

df['var2'] = pd.Series([round(val, 2) for val in df['var2']], index = df.index)
df['var3'] = pd.Series(["{0:.2f}%".format(val * 100) for val in df['var3']], index = df.index)

La fonction round arrondit un nombre à virgule flottante au nombre de décimales fournies en tant que second argument de la fonction.

Le formatage de chaîne vous permet de représenter les nombres comme vous le souhaitez. Vous pouvez changer le nombre de décimales affichées en changeant le nombre avant le f.

p.s. Je ne savais pas si votre nombre de pourcentages avait déjà été multiplié par 100. S'ils l'ont clairement indiqué, vous souhaiterez modifier le nombre de décimales affichées et supprimer la multiplication de cent.

30
Woody Pride

La réponse acceptée suggère de modifier les données brutes à des fins de présentation, ce que vous ne voulez généralement pas. Imaginez que vous deviez effectuer des analyses supplémentaires avec ces colonnes et que vous ayez besoin de la précision perdue avec l’arrondi.

Vous pouvez modifier le formatage de colonnes individuelles dans des cadres de données, dans votre cas:

output = df.to_string(formatters={
    'var1': '{:,.2f}'.format,
    'var2': '{:,.2f}'.format,
    'var3': '{:,.2%}'.format
})
print(output)

Pour votre information, '{:,.2%}'.format(0.214) donne 21.40%, Il n'est donc pas nécessaire de multiplier par 100.

Vous n'avez plus un joli tableau HTML mais une représentation textuelle. Si vous devez rester en HTML, utilisez plutôt la fonction to_html.

from IPython.core.display import display, HTML
output = df.to_html(formatters={
    'var1': '{:,.2f}'.format,
    'var2': '{:,.2f}'.format,
    'var3': '{:,.2%}'.format
})
display(HTML(output))

Mise à jour

A partir de pandas 0.17.1, la vie est devenue plus facile et nous pouvons obtenir immédiatement une belle table html:

df.style.format({
    'var1': '{:,.2f}'.format,
    'var2': '{:,.2f}'.format,
    'var3': '{:,.2%}'.format,
})
85
linqu

Vous pouvez également définir le format par défaut pour float:

pd.options.display.float_format = '{:.2f}%'.format
26
Romain Jouin

Comme suggéré par @linqu, vous ne devez pas modifier vos données pour la présentation. Depuis pandas 0.17.1, le formatage (conditionnel) a été facilité. Citer le documentation :

Vous pouvez appliquer une mise en forme conditionnelle , le style visuel d'un DataFrame en fonction des données qu'il contient, en utilisant le DataFrame.style propriété. Ceci est une propriété qui retourne un pandas.Styler objet, qui contient des méthodes utiles pour formater et afficher DataFrames.

Pour votre exemple, ce serait (la table habituelle apparaîtra dans Jupyter):

df.style.format({
    'var1': '{:,.2f}'.format,
    'var2': '{:,.2f}'.format,
    'var3': '{:,.2%}'.format,
})
21
mdeff

Juste une autre façon de le faire si vous avez besoin de le faire sur une plus grande plage de colonnes

en utilisant applymap

df[['var1','var2']] = df[['var1','var2']].applymap("{0:.2f}".format)
df['var3'] = df['var3'].applymap(lambda x: "{0:.2f}%".format(x*100))

applymap est utile si vous devez appliquer la fonction sur plusieurs colonnes. c'est essentiellement une abréviation de ce qui suit pour cet exemple spécifique:

df[['var1','var2']].apply(lambda x: map(lambda x:'{:.2f}%'.format(x),x),axis=1)

Grande explication ci-dessous de apply, map applymap:

Différence entre les méthodes map, applymap et apply dans les pandas

4
RK1

Il suffit de faire:

df.style.format({'var1': "{:.2f}",'var2': "{:.2f}",'var3': "{:.2%}"})

Donne:

var1    var2    var3
id          
0   1.46    1.50    -0.57%
1   1.58    1.61    -0.51%
2   1.63    1.65    -0.48%
3   1.67    1.69    -0.35%
4   1.71    1.71    -0.31%
5   1.74    1.74    -0.12%
6   1.78    1.77    -0.17%
7   1.81    1.80    -0.20%
8   1.85    1.82    -0.14%
9   1.94    1.87    0.57%
4
Poudel

En tant qu’approche similaire à la réponse acceptée qui pourrait être considérée un peu plus lisible, élégante et générale (YMMV), vous pouvez utiliser la méthode map:

# OP example
df['var3'].map(lambda n: '{:,.2%}'.format(n))

# also works on a series
series_example.map(lambda n: '{:,.2%}'.format(n))

En termes de performances, ceci est assez proche (légèrement plus lent) que la solution OP.

En passant, si vous choisissez d'aller au pd.options.display.float_format _ route, envisagez l’utilisation d’un gestionnaire de contexte pour gérer l’état selon ceci exemple: numpy parallèle .

1
circld