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%.
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.
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,
})
Vous pouvez également définir le format par défaut pour float:
pd.options.display.float_format = '{:.2f}%'.format
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 leDataFrame.style
propriété. Ceci est une propriété qui retourne unpandas.Styler
objet, qui contient des méthodes utiles pour formater et afficherDataFrames
.
Pour votre exemple, ce serait (la table habituelle apparaîtra dans Jupyter):
df.style.format({
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format,
})
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
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%
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 .