1

I am trying to draw a horizontal bar chart, but the second data columns does not appear at all!

df = pd.DataFrame(dict(graph=["Indian","Egyptian","Emirati","Philippino","Syrian","Pakistani","Jordanian",
          "British","Lebanese","American","Chinese","Ukrainian","Canadian","Russian",
          "French","Saudi","Sudanese","Moroccan","Nigerian","Palestinian","German","Iranian",
          "Italian","Turkish","Tunisian"],
                           n=[33060621,28185470,25327222,14033365,13895316,13335555,13067230,9065737,8871022,3914119,3875486,
         3505868,3421358,3407623,3067701,2940321,2824929,2620922,2510789,2439167,1874219,1800495,1852571,1415189,1657462], 
                           m=[13504,13762,9671,4568,4995,8016,6808,5559,5456,4137,2802,1011,2386,1806,4408,2002,1141,1530,916,992,1933,1651,
          1628,1469,839])) 

ind = np.arange(len(df))
width = 0.4

fig, ax = plt.subplots(figsize=(15,20))
ax.barh(ind, df.n, width, color='red', label='N')
ax.barh(ind + width, df.m, width, color='green', label='M')

ax.set(yticks=ind + width, yticklabels=df.graph, ylim=[2*width - 1, len(df)])
ax.legend()

plt.show()

https://drive.google.com/file/d/12TB_pArFWLbCI_ZhePkEfVMpnWxTj885/view?usp=sharing

I would like some help :

  1. Why does only one data column is appear and the other is hidden ?
  2. Can I have different range for each column? For example, put upper x-axis for the fist column and the lower x-axis is for the second column?
  3. Why are the country's names are shifted?
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
  • 1
    The values of column `m` is too small to be shown on the same axis as column `n`. – Henry Yik Oct 16 '21 at 18:48
  • One line to rule them all: `ax = df.set_index('graph').plot(kind='barh', figsize=(15, 8), logx=True)` [plot](https://i.stack.imgur.com/5sm8Z.png) using **`pandas 1.3.3`, `matplotlib 3.4.3`** to plot the dataframe directly with `pandas.DataFrame.plot`. – Trenton McKinney Oct 17 '21 at 00:36

2 Answers2

1
  1. The other data column is not visible in the plot, because its values are so much smaller. To change that, you could scale them up for the plot, e.g. by a factor of 1000.
  2. You can add a second x-axis to the plot with ax.twiny(), see below.
  3. Where the y labels appear relative to the bars depends on the width values you add to the index. The code below shows a way to centralize them for each pair of bars.
ind = np.arange(len(df))
width = 0.4
scale = 1000

xticks = [0, 10_000_000, 20_000_000, 30_000_000]
limits = [0, 35_000_000]

fig, ax = plt.subplots(figsize=(15,20))

ax.barh(ind + 0.5 * width, df.n, width, color='red', label='N')
ax.barh(ind + 1.5 * width, scale * df.m, width, color='green', label='M')
ax.xaxis.get_major_formatter().set_useOffset(False)
ax.set(yticks=ind + width, yticklabels=df.graph, ylim=[2*width - 1, len(df)],
       xticks=xticks, xticklabels=['0', '10 M', '20 M', '30 M'], xlim=limits)

ax2 = ax.twiny()
ax2.xaxis.get_major_formatter().set_useOffset(False)
ax2.set(xticks=xticks, xticklabels=['0', '10 K', '20 K', '30 K'], xlim=limits)

ax.legend()
plt.show()

bar plot with second x axis

Arne
  • 9,990
  • 2
  • 18
  • 28
  • is the top x-axis refrence for the red bars (m) only ?? and the bottom for the green ones? if yes, How the graph redear will know that? – almegdadi Oct 16 '21 at 20:10
  • That's up to you. You'll have to add an explanation and perhaps additional visual clues if you want to plot on two different scales in the same plot like this. The way I labeled the ticks above, the upper axis is for the green bars and the lower one for the red bars. I thought this made sense visually, because each green bar is above the red one. – Arne Oct 16 '21 at 20:23
  • @Arne .. Thank you very much .. what if i would like to color the access ?? for example make the label colors red and green to make it easier to track ? – Lenda Marwan Oct 27 '21 at 09:19
  • See this question: https://stackoverflow.com/questions/4761623/how-to-change-the-color-of-the-axis-ticks-and-labels-for-a-plot-in-matplotlib – Arne Oct 27 '21 at 15:06
1
import plotly.graph_objects as go
from plotly.subplots import make_subplots

fig=make_subplots()   

fig.update_layout(xaxis2={ 'overlaying': 'x', 'side': 'top'})

fig.add_trace(
    go.Bar(name='M', y=df['graph'], x=df.m, orientation='h'))
fig.add_trace(
    go.Bar(name='N', y=df['graph'], x=df.n, orientation='h'))
fig.data[1].update(xaxis='x2')
fig.update_layout(width=700, height=475)

fig.show()
tzinie
  • 717
  • 5
  • 9