简体   繁体   English

如何 plot 混合柱和线 plot 并获得 x 轴作为年份

[英]How to plot a mixed bar and line plot and get the x-axis as year

I am a new to Python and currently trying to plot the data in dataframe with barchart and line.我是 Python 的新手,目前正在尝试使用条形图和折线图 plot dataframe 中的数据。

[Environment] [环境]

OS: Windows 7 - 64bit
Visual Studio Code 1.45.1
Python 2020.6.91350

The following is the base data in csv format and it is read by the code below.下面是csv格式的基础数据,通过下面的代码读取。

[testData.csv] [测试数据.csv]

year,ordered,sold,YoY-ordered,YoY-sold
2015,100,80,0.1,-0.05
2016,120,100,0.2,0.25
2017,100,130,-0.166666667,0.3
2018,80,90,-0.2,-0.307692308
2019,90,95,0.125,0.055555556
2020,100,90,0.111111111,-0.052631579

[code.py] [代码.py]

import matplotlib as mplt
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

df = pd.read_csv('./testData.csv')
df=df.set_index("year")

idxO = "ordered"
idxS = "sold"
idxOYoY = "YoY-ordered" 
idxSYoY = "YoY-sold"

fig = plt.figure(figsize=(12,5))
fig.suptitle("title")
ax1 = fig.add_subplot()
ax2 = ax1.twinx()
ax1.set_ylabel("Ordered, Sold")
ax2.set_ylabel("YoY")

df[[idxO, idxS]].plot(ax=ax1,kind="bar", color=["black","gray"])
df[[idxOYoY, idxSYoY]].plot(ax=ax2,kind="line", marker="o", color=["blue","lightblue"])

handler1, label1 = ax1.get_legend_handles_labels()
handler2, label2 = ax2.get_legend_handles_labels()
ax1.legend(handler1 + handler2, label1 + label2)
ax2.get_legend().remove()
plt.show()

It gives the graph below.它给出了下图。

结果1

I found that I can get the graph I want, except the values of x-axis, if I do not set year as the index of the dataframe (commented out df=df.set_index("year")) .我发现如果我不将年份设置为 dataframe 的索引(注释掉df=df.set_index("year")) ,我可以获得我想要的图表,除了 x 轴的值。

结果2

What I want to do is create the plot with the correct index (year) for x-axis.我想要做的是为 x 轴创建具有正确索引(年份)的 plot。

I prefer to convert dataframe columns to lists:我更喜欢将 dataframe 列转换为列表:

...
#covert dataframe columns to lists
years = df[0].to_numpy().tolist()[1:]
ordered = df[1].to_numpy().tolist()[1:]
sold = df[2].to_numpy().tolist()[1:]
YoY_ordered = df[3].to_numpy().tolist()[1:]
YoY_sold = df[4].to_numpy().tolist()[1:]

fig = plt.figure(figsize=(12,5))
fig.suptitle("title")
ax1 = fig.add_subplot()
ax2 = ax1.twinx()
ax1.set_ylabel("Ordered, Sold")
ax2.set_ylabel("YoY")

year_indexes = np.arange(len(years))
WIDTH = 0.25
ax1.bar(year_indexes - WIDTH/2, ordered, width=WIDTH, color="orange", label="Ordered")
ax1.bar(year_indexes + WIDTH/2, sold, width=WIDTH, color="blue", label="Sold")
ax2.plot(year_indexes, YoY_ordered, color = "red", label = "YoY_ordered")
ax2.plot(year_indexes, YoY_sold, color = "green", label = "YoY_sold")

plt.xticks(year_indexes,years)
ax1.legend(loc = "upper left")
ax2.legend()
plt.show()

在此处输入图像描述

  • This type of plot is easily created with pandas.DataFrame.plot and .twinx()这种类型的 plot 很容易用pandas.DataFrame.plot.twinx()创建
    • As shown in the code below, all of the label information can be set in the plot如下代码所示,可以在plot中设置label的所有信息
    • matplotlib.axes.Axes is returned, so assign the plot to ax , and then create ax2 . matplotlib.axes.Axes被返回,因此将 plot 分配给ax ,然后创建ax2
  • 'year' is not set as the index in the following code 'year'未设置为以下代码中的索引
import pandas as pd
import matplotlib.pyplot as plt

# test data
data = {'year': [2015, 2016, 2017, 2018, 2019, 2020], 'ordered': [100, 120, 100, 80, 90, 100], 'sold': [80, 100, 130, 90, 95, 90], 'YoY-ordered': [0.1, 0.2, -0.166666667, -0.2, 0.125, 0.111111111], 'YoY-sold': [-0.05, 0.25, 0.3, -0.307692308, 0.055555556, -0.052631579]}
df = pd.DataFrame(data)

# display(df)
   year  ordered  sold  YoY-ordered  YoY-sold
0  2015      100    80     0.100000 -0.050000
1  2016      120   100     0.200000  0.250000
2  2017      100   130    -0.166667  0.300000
3  2018       80    90    -0.200000 -0.307692
4  2019       90    95     0.125000  0.055556
5  2020      100    90     0.111111 -0.052632

# plot the bars with a pandas.DataFrame.plot and assign the plot to ax
ax = df.plot.bar(x='year', y=['ordered', 'sold'], ylabel='Ordered / Sold', xlabel='Year', color=['black', 'gray'], figsize=(12, 5))

# create ax2
ax2 = ax.twinx()

# plot the lines
df.plot(x='year', y=['YoY-ordered', 'YoY-sold'], marker='o', ylabel='YoY', color=['blue', 'lightblue'], ax=ax2)

# locate the legend
ax.legend(loc="upper left")
ax2.legend(loc='upper right')

plt.show()

在此处输入图像描述

Code From OP来自 OP 的代码

  • Incidentally, I also ran your code, with 'year' as the dataframe index, and it plots without issue.顺便说一句,我还运行了您的代码,其中'year'作为 dataframe 索引,并且绘制没有问题。
  • All code was tested in JupyterLab, Spyder, a bare python interpreter, and PyCharm Pro 2020.3.2, with pandas 1.2.0 and matplotlib 3.3.2 .所有代码都在 JupyterLab、Spyder、裸机 python 解释器和 PyCharm Pro 2020.3.2 中进行了测试,其中pandas 1.2.0matplotlib 3.3.2
  • I use the Anaconda distribution , which I recommend, and I update weekly with conda update --all , otherwise you'll need to update with pip我使用我推荐的Anaconda 发行版,我每周使用conda update --all进行更新,否则您需要使用pip进行更新

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM