0

I have plotted some data with this code:

plt.rcdefaults()
fig, ax = plt.subplots(figsize=(10,6))
# Example data
people = data_year[data_year.columns[1]]
y_pos = np.arange(len(people))
#performance = 3 + 10 * np.random.rand(len(people))
performance=data_year[data_year.columns[2]]
error = np.random.rand(len(people))
rects=ax.barh(y_pos, performance, xerr=error, align='center')
ax.invert_yaxis()  # labels read top-to-bottom
ax.set_xlabel('population (thousands)' , fontsize=15)
ax.text(0.9, 0.1, year,verticalalignment='bottom', horizontalalignment='right',transform=ax.transAxes,color='red',size=30)
for i, (p, pr) in enumerate(zip(data_year["Country or area"], data_year["Urban Agglomeration"])):
    plt.text(s=p, x=1, y=i, color='black', verticalalignment="top", horizontalalignment="left", size=8)
    plt.text(s=pr , x=1, y=i, color='black',verticalalignment="bottom",horizontalalignment="left", size=10)
display(plt.show)

and the outcome is like this enter image description here but the outcome I need is something like this enter image description here

How can I change the place of labels?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
nemo92world
  • 101
  • 8

1 Answers1

1

Select data from downloaded file

  • Download a data file from the link, or use the sample dataframe, df, at the bottom of the answer.
import pandas as pd
import matplotlib.pyplot as plt

# load the files
data = pd.read_csv('data/UNdata_Export_20210131_205829459.csv')

# filter data
data = data.loc[(data['City type'] == 'City proper') & (data['Sex'] == 'Both Sexes')][['Country or Area', 'City', 'Value', 'Year']]

# sort data
data = data.sort_values('Value', ascending=False)

# select top 10 rows
df = data.iloc[:10]

Plot using OP method

  • This implementation unnecessarily extracts dataframe columns into new variables (e.g. people)
people = df[df.columns[2]]
y_pos = np.arange(len(people))

error = np.random.rand(len(people))

fig, ax = plt.subplots(figsize=(10,6))

rects = ax.barh(y_pos, people, xerr=error, align='center')

ax.invert_yaxis()  # labels read top-to-bottom
ax.set_xlabel('population' , fontsize=15)

ax.text(0.9, 0.1, 2015, va='bottom', ha='right', transform=ax.transAxes, color='red',size=30)

for i, (p, pr) in enumerate(zip(df['Country or Area'], df['City'])):

    # extract the rectangles from ax
    rectangle = ax.patches[i]
    
    # get the x for the bar
    x = rectangle.get_x()
    
    # get the width
    width = rectangle.get_width()
    
    # calculate the label position
    x_label = x + width
    
    # use the rectangle x to plot the text and set the ha to right instead of left
    plt.text(s=p, x=x_label, y=i, color='black', va="top", ha="right", size=8, weight='bold')
    plt.text(s=pr, x=x_label, y=i, color='black', va="bottom", ha="right", size=10, weight='bold')
    
display(plt.show)

Streamlined Implementation

# plot the dataframe
ax = df.plot.barh(y='Value', figsize=(10, 6), legend=False, width=0.8)
ax.set_xlabel('population' , fontsize=15)

ax.set(yticklabels=[])  # remove the y tick labels
ax.tick_params(left=False)  # remove the ticks

ax.invert_yaxis()

ax.text(0.9, 0.1, 2015, va='bottom', ha='right', transform=ax.transAxes, color='red',size=30)

for i, (p, pr) in enumerate(zip(df['Country or Area'], df['City'])):

    # extract the rectangles from ax
    rectangle = ax.patches[i]
    
    # get the x for the bar
    x = rectangle.get_x()
    
    # get the width
    width = rectangle.get_width()
    
    # calculate the label position
    x_label = x + width
    
    # use the rectangle x to plot the text and set the ha to right instead of left
    plt.text(s=p, x=x_label, y=i, color='black', va="top", ha="right", size=8, weight='bold')
    plt.text(s=pr, x=x_label, y=i, color='black', va="bottom", ha="right", size=10, weight='bold')
    
plt.show()

Plot Result

enter image description here

df sample

  • Test data if website data is no longer available
data = {'Country or Area': ['Republic of Korea', 'Japan', 'Mexico', 'United States of America', 'China, Hong Kong SAR', 'Singapore', 'Chile', 'Australia', 'Australia', 'Jordan'], 'City': ['SEOUL', 'TOKYO', 'MEXICO, CIUDAD DE', 'New York (NY)', 'HONG KONG SAR', 'SINGAPORE', 'SANTIAGO', 'Sydney', 'Melbourne', 'AMMAN'], 'Value': [9860372.0, 9272740.0, 8854560.0, 8550405.0, 7291300.0, 5535002.0, 5150010.0, 4526479.0, 4353514.0, 4007526.0], 'Year': ['2015', '2015', '2015', '2015', '2015', '2015', '2015', '2015', '2015', '2015']}
df = pd.DataFrame(data)

display(df)
            Country or Area               City      Value  Year
0         Republic of Korea              SEOUL  9860372.0  2015
1                     Japan              TOKYO  9272740.0  2015
2                    Mexico  MEXICO, CIUDAD DE  8854560.0  2015
3  United States of America      New York (NY)  8550405.0  2015
4      China, Hong Kong SAR      HONG KONG SAR  7291300.0  2015
5                 Singapore          SINGAPORE  5535002.0  2015
6                     Chile           SANTIAGO  5150010.0  2015
7                 Australia             Sydney  4526479.0  2015
8                 Australia          Melbourne  4353514.0  2015
9                    Jordan              AMMAN  4007526.0  2015
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158