The accepted answer suggests to modify the raw data for presentation purposes, something you generally do not want. Imagine you need to make further analyses with these columns and you need the precision you lost with rounding.
You can modify the formatting of individual columns in data frames, in your case:
output = df.to_string(formatters={
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format
})
print(output)
For your information '{:,.2%}'.format(0.214) yields 21.40%, so no need for multiplying by 100.
You don't have a nice HTML table anymore but a text representation. If you need to stay with HTML use the to_html function instead.
from IPython.core.display import display, HTML
output = df.to_html(formatters={
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format
})
display(HTML(output))
Update
As of pandas 0.17.1, life got easier and we can get a beautiful html table right away:
df.style.format({
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format,
})
Answer from linqu on Stack OverflowThe accepted answer suggests to modify the raw data for presentation purposes, something you generally do not want. Imagine you need to make further analyses with these columns and you need the precision you lost with rounding.
You can modify the formatting of individual columns in data frames, in your case:
output = df.to_string(formatters={
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format
})
print(output)
For your information '{:,.2%}'.format(0.214) yields 21.40%, so no need for multiplying by 100.
You don't have a nice HTML table anymore but a text representation. If you need to stay with HTML use the to_html function instead.
from IPython.core.display import display, HTML
output = df.to_html(formatters={
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format
})
display(HTML(output))
Update
As of pandas 0.17.1, life got easier and we can get a beautiful html table right away:
df.style.format({
'var1': '{:,.2f}'.format,
'var2': '{:,.2f}'.format,
'var3': '{:,.2%}'.format,
})
You could also set the default format for float :
pd.options.display.float_format = '{:.2%}'.format
Use '{:.2%}' instead of '{:.2f}%' - The former converts 0.41 to 41.00% (correctly), the latter to 0.41% (incorrectly)
Hi - how to convert decimal numbers such as 0.0555 to percent to display percentage sign as 5.55% ?
I tried below I have two problems:
-
some values have 1 and some two decimals in my output excel file.
-
when I export to excel it's string not value. When I convert to value manually in excel I get two see two decimal places.
How to solve this in pandas, to display two decimal places with percent sign and to be value. Keep in mind that excel file will feed client database and can't be text or string.
df["Value"]= df["Value"].astype(float)
df["Value"]=df["Value"]*100
df["Value"]=df["Value"].round(2)
df["Value"]=df["Value"].astype(str) + "%"
python - pandas convert columns to percentages of the totals - Stack Overflow
Formatting floating point values as percent in column_config
pandas - format number (based on calculation) as a percentage to two decimal places using python - Stack Overflow
Converting pandas column to percentage
Showing us what CSV_DAX['EL4F'] and date_DAX looks like would help us a lot. What you have seems okay with the limited information you gave us.
Videos
You can do this using basic pandas operators .div and .sum, using the axis argument to make sure the calculations happen the way you want:
cols = ['<80%', '80-90', '>90']
df[cols] = df[cols].div(df[cols].sum(axis=1), axis=0).multiply(100)
- Calculate the sum of each column (
df[cols].sum(axis=1).axis=1makes the summation occur across the rows, rather than down the columns. - Divide the dataframe by the resulting series (
df[cols].div(df[cols].sum(axis=1), axis=0).axis=0makes the division happen across the columns. - To finish, multiply the results by
100so they are percentages between 0 and 100 instead of proportions between 0 and 1 (or you can skip this step and store them as proportions).
df/df.sum()
If you want to divide the sum of rows, transpose it first.
You forgot to make a string:
format_percent = '{:.2f}'.format(percent_val)
# ^ ^
Also, if you want a percent, you'll need to multiply by 100, and if you're on Python 2 (I can't tell), you'll either need to use floats or from __future__ import division.
If you want to round the number to two decimal places, rather than creating formatted output, there's the round function:
rounded = round(percent_val, 2)
Then your output will be a float instead of a string, and you can keep doing math with it.
You can plug the display format into pandas' display options:
In [11]: df = pd.DataFrame(np.random.randn(2, 2))
In [12]: df
Out[12]:
0 1
0 1.058814 -0.011675
1 -0.002627 -0.152505
In [13]: pd.options.display.float_format = '{:.2f}'.format
In [14]: df
Out[14]:
0 1
0 1.06 -0.01
1 -0.00 -0.15
See more about python's string formatting here.
Note: the numbers themselves are unaffected (they haven't been rounded):
In [15]: df.iloc[0, 0]
Out[15]: 1.058814403984879
Hey folks, I downloaded a CSV file from the internet and I wanted to convert one column into percentage with the first value in the column being 100 %. My approach looks as follows:
In the first step I fetch the first value of the column and make it a variable:
DAX_first=CSV_DAX['EL4F'].iloc[0]
In the second step I try to turn everything into percentages by the following:
plt.plot(date_DAX, CSV_DAX['EL4F']/DAX_first*100)
data_DAX contains the values for the X-axis obviously. The plot that I obtain doens't start at 100% but instead at around 60 %. Probably there's a blatant mistake somewhere but I don't see it at the moment. Can anyone spot the mistake?
You could use .apply('{:.0%}'.format):
import pandas as pd
df = pd.DataFrame([(168,219,185,89,112), (85,85,84,41,46)],
index=['Total Listings', 'Total Sales'], columns=list(range(1,6)))
df.loc['Total Sales Rate'] = ((df.loc['Total Sales']/df.loc['Total Listings'])
.apply('{:.0%}'.format))
print(df)
yields
1 2 3 4 5
Total Listings 168 219 185 89 112
Total Sales 85 85 84 41 46
Total Sales Rate 51% 39% 45% 46% 41%
Notice that the Python str.format method has a built-in % format which multiplies the number by 100 and displays in fixed ('f') format, followed by a percent sign.
It is important to be aware that Pandas DataFrame columns must have a single dtype. Changing one value to a string forces the entire column to change
its dtype to the generic object dtype. Thus the int64s or int32s in the
Total Listings and Total Sales rows get recast as plain Python ints. This
prevents Pandas from taking advantage of fast NumPy-based numerical operations
which only work on native NumPy dtypes (like int64 or float64 -- not
object).
So while the above code achieves the desired look, it isn't advisable to use this if further computation is to be done on the DataFrame. Instead, only convert to strings at the end if you need to do so for presentation.
Or, alternatively, transpose your DataFrame so the Total Sales Rate strings are in a column, not a row:
import pandas as pd
df = pd.DataFrame([(168,219,185,89,112), (85,85,84,41,46)],
index=['Total Listings', 'Total Sales'], columns=list(range(1,6))).T
df['Total Sales Rate'] = ((df['Total Sales']/df['Total Listings'])
.apply('{:.0%}'.format))
print(df)
yields
Total Listings Total Sales Total Sales Rate
1 168 85 51%
2 219 85 39%
3 185 84 45%
4 89 41 46%
5 112 46 41%
The reason why
block_combine.loc["Total Sales Rate"] = pd.Series(["{0:.0f}%".format(val * 100) for val in block_combine.loc["Total Sales Rate"]])
shifted the values to the left by one column is because the new Series has an index which starts at 0 not 1. Pandas aligns the index of the Series on the right with the index of block_combine.loc["Total Sales Rate"] before assigning values to block_combine.loc["Total Sales Rate"].
Thus, you could alternatively have used:
block_combine.loc["Total Sales Rate"] = pd.Series(["{0:.0f}%".format(val * 100)
for val in block_combine.loc["Total Sales Rate"]],
index=block_combine.columns)
df = pd.DataFrame({
1: [168,85],
2: [219,85],
3: [185,84],
4: [89,41],
5: [112,46]
}, index=['Total Listings', 'Total Sales'])
total_sales_rate = pd.Series(df.loc['Total Sales'] / df.loc['Total Listings'] * 100, name='Total Sales Rate').round()
df = df.append(total_sales_rate)
Result...
1 2 3 4 5
Total Listings 168 219 185 89 112
Total Sales 85 85 84 41 46
Total Sales Rate 51 39 45 46 41
Use pandas' broadcasting operations:
df.rating = (df.rating * 100).astype(str) + '%'
df
name rating
0 Johnny 100.0%
1 Brad 90.0%
Alternatively, using df.mul and df.add:
df.rating = df.rating.mul(100).astype(str).add('%')
df
name rating
0 Johnny 100.0%
1 Brad 90.0%
df['rating'] = df['rating'].mul(100).astype(int).astype(str).add('%')
print(df)
Output:
name rating
0 Johnny 100%
1 Brad 90%
Toy example:
df=DataFrame({
'No Show (%)':[5e-01, 4e-01]
})
df
Input
No Show (%)
0 0.5
1 0.4
Code
mergedgc.style.format({"No Show (%)": "{:.2%}"})
can be replaced by
df['No Show (%)'] = df['No Show (%)'].transform(lambda x: '{:,.2%}'.format(x))
Output
No Show (%)
0 50.00%
1 40.00%
Edit
Plot
df['No Show (%)'].replace('\%','', regex=True).astype(float).plot()

Try this :
df["No_show_percentage"] = ((df["NoShow"]/df["Booked"])*100).round(2)
df```
Result:
Booked NoShow No_show_percentage
0 121 64 52.89
1 4 2 50.00