在 Python 中从 CSV 文件创建混合图表

Posted

技术标签:

【中文标题】在 Python 中从 CSV 文件创建混合图表【英文标题】:Creating Mixed Charts from CSV Files in Python 【发布时间】:2020-04-04 05:43:20 【问题描述】:

我开发了一个 perl 脚本,它围绕数据进行操作,并为我提供了一个最终的 csv 文件。不幸的是,我的系统不支持 perl 中的图形和图表包,由于工作限制,我无法安装它们。所以我想尝试获取 csv 文件并在 Python 中组合一些东西来生成一个混合图。我希望第一列是 x 轴上的标签。接下来的三列是条形图。第四列是横过 x 轴的线。

这里是示例数据:

Name      PreviousWeekProg     CurrentWeekProg     ExpectedProg     Target
Dan              94                   92                 95           94
Jarrod           34                   56                 60           94
Chris            45                   43                 50           94
Sam              89                   90                 90           94
Aaron            12                   10                 40           94
Jenna            56                   79                 80           94
Eric             90                   45                 90           94

我正在寻找这样的图表:

我做了一些研究,但和我在 python 中一样一无所知,我想寻求一些关于在 python 中用于混合图表和图形的好模块的指导。对不起,如果我的帖子含糊不清。除了在线查看其他参考资料外,我对如何进行此操作一无所知。另外,我的 python 版本是 3.8,并且我确实安装了 matplotlib(这是我之前推荐使用的)。

【问题讨论】:

您好,我的回答对您的问题有帮助吗? @ShaunLowis 这非常有帮助,但我仍在尝试了解它的一些基础知识:(例如,我在尝试读取 csv 开始时遇到错误。似乎是一些基本的东西,但我还没有弄清楚。 那是公平的,您可以将我的答案标记为正确,然后提出与您的错误相关的另一个问题并在评论中标记我,我可以尝试提供帮助吗? 【参考方案1】:

由于@ShaunLowis 的答案没有包含完整的示例,我想我会添加一个。就阅读.csv 文件而言,在这种情况下,最好的方法可能是使用pandas.read_csv(),正如另一个答案所指出的那样。在此示例中,我将文件命名为 test.csv 并将其放在我运行脚本的同一目录中

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

df = pd.read_csv("./test.csv")
names = df['Name'].values
x = np.arange(len(names))
w = 0.3
plt.bar(x-w, df['PreviousWeekProg'].values, width=w, label='PreviousWeekProg')
plt.bar(x, df['CurrentWeekProg'].values, width=w, label='CurrentWeekProg')
plt.bar(x+w, df['ExpectedProg'].values, width=w, label='ExpectedProg')
plt.plot(x, df['Target'].values, lw=2, label='Target')
plt.xticks(x, names)
plt.ylim([0,100])
plt.tight_layout()
plt.xlabel('X label')
plt.legend(loc='upper center', bbox_to_anchor=(0.5, -0.1), fancybox=True, ncol=5)
plt.savefig("CSVBarplots.png", bbox_inches="tight")
plt.show()


说明

来自read_csv()pandas 文档(与示例无关的参数除外),

pandas.read_csv(filepath_or_buffer)

将逗号分隔值 (csv) 文件读入 DataFrame。filepath_or_bufferstr、路径对象或类文件对象 /p>

任何有效的字符串路径都是可接受的。该字符串可以是一个 URL。 [...] 如果你想传入一个路径对象,pandas 接受任何os.PathLike。 通过类文件对象,我们指的是具有read() 方法的对象,例如文件处理程序(例如通过内置open 函数)或StringIO

在本例中,我指定的是文件的路径,而不是文件对象。

names = df['Name'].values

这会提取'Name' 列中的值并将它们转换为numpy.ndarray 对象。为了用一个名称绘制多个条形图,我引用了this answer。但是,为了使用这种方法,我们需要一个与 names 数组长度相同的浮点数 x 数组,因此

x = np.arange(len(names))

然后设置条的宽度并相应地偏移第一条和第三条,作为referenced answer中的轮廓

w = 0.3
plt.bar(x-w, df['PreviousWeekProg'].values, width=w, label='PreviousWeekProg')
plt.bar(x, df['CurrentWeekProg'].values, width=w, label='CurrentWeekProg')
plt.bar(x+w, df['ExpectedProg'].values, width=w, label='ExpectedProg')

来自matplotlib.pyplot.bar 页面(未使用的非位置参数除外),

matplotlib.pyplot.bar(x, height, width=0.8)

条形图位于x [...],它们的尺寸由widthheight 给出。xheightwidth 中的每一个都可以是应用于所有条形的标量,也可以是长度为 N 的序列,为每个条形提供单独的值。

在这种情况下,xheight 是值序列(每个条形图不同),width 是标量(每个条形图相同)。

接下来是target 的行,它非常简单,只需将之前创建的x 值与'Target' 列中的值进行对比

plt.plot(x, df['Target'].values, lw=2, label='Target')

其中lw 指定线宽。 免责声明:如果.csv 的每一行的目标值不同,这仍然有效,但看起来可能与您想要的不完全一样。

接下来的两行,

plt.xticks(x, names)
plt.ylim([0,100])

只需在条形下方的适当x 位置添加名称,然后将y 限制设置为跨越间隔[0, 100]

这里的最后一点是在情节下方添加图例,

plt.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), fancybox=True)

请参阅this answer,了解如何根据需要进行调整。

【讨论】:

这太完美了。你的解释很详细也很中肯!我需要一个小时来奖励赏金。 @sfr 谢谢,很高兴它有帮助 我还有一个问题。除了使用 plt.show 之外,还有什么方法可以将其保存到本地图像(jpeg 或 png)? @sfr 你想使用plt.savefig("filename.png")。此外,我建议使用bbox_inches='tight' 删除在输出周围添加的大量空白。 (所以完整的plt.savefig("filename.png", bbox_inches='tight' 我刚刚在阅读您的评论之前试了一下,效果很好。再次感谢您的所有帮助。【参考方案2】:

我建议使用Pandas 库的'read_csv()' 实用程序读取您的.csv 文件,如下所示:

import pandas as pd

df = pd.read_csv(filepath)

这会将信息存储在 Dataframe 对象中。然后,您可以通过以下方式访问您的列:

my_column = df['PreviousWeekProg']

之后你可以调用:

my_column.plot(kind='bar')

在您希望绘制的任何列上。 配置子图是另一回事,我建议使用matplotlib's pyplot。

我建议从这个图形和轴对象声明开始,然后从那里开始:

fig = plt.figure()
ax1 = plt.subplot()
ax2 = plt.subplot()
ax3 = plt.subplot()
ax4 = plt.subplot()

您可以在哪里阅读有关添加坐标区数据的更多信息here。

如果这有帮助,请告诉我!

【讨论】:

如果您正在为实施而苦苦挣扎,如果我不清楚任何事情,这篇文章应该会有所帮助:***.com/questions/33631163/…【参考方案3】:

您可以使用包seaborn中的参数hue。首先,您需要使用函数melt 重塑数据集:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

df1 = df.melt(id_vars=['Name', 'Target'])
print(df1.head(10))

输出:

     Name  Target          variable  value
0     Dan      94  PreviousWeekProg     94
1  Jarrod      94  PreviousWeekProg     34
2   Chris      94  PreviousWeekProg     45
3     Sam      94  PreviousWeekProg     89
4   Aaron      94  PreviousWeekProg     12
5   Jenna      94  PreviousWeekProg     56
6    Eric      94  PreviousWeekProg     90
7     Dan      94   CurrentWeekProg     92
8  Jarrod      94   CurrentWeekProg     56
9   Chris      94   CurrentWeekProg     43

现在您可以在函数barplot 中使用'variable' 列作为hue 参数:

fig, ax = plt.subplots(figsize=(10, 5)) # set the size of a figure
sns.barplot(x='Name', y='value', hue='variable', data=df1) # plot

xmin, xmax = plt.xlim() # get x-axis limits
ax.hlines(y=df1['Target'], xmin=xmin, xmax=xmax, color='red') # add multiple lines
# or ax.axhline(y=df1['Target'].max()) to add a single line

sns.set_style("whitegrid") # use the whitegrid style
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.06), ncol=4, frameon=False) # move legend to the bottom
plt.title('Student Progress', loc='center') # add title
plt.yticks(np.arange(df1['value'].min(), df1['value'].max()+1, 10.0)) # change tick frequency
plt.xlabel('') # set xlabel
plt.ylabel('') # set ylabel

plt.show() # show plot

【讨论】:

以上是关于在 Python 中从 CSV 文件创建混合图表的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中从数据库创建 CSV 文件?

我可以在 python3 中从 excel 文件(不是 CSV)创建字典吗?

如何在 Python 中使用 csv 中的字符串创建图表或折线图

在 python 中从模板文件和 csv 数据生成输出文件

在 Python 中从 csv 文件生成字符串集

如何在python中从csv文件构建带有边框的表格