在 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_buffer
:str、路径对象或类文件对象 /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
[...],它们的尺寸由width
和height
给出。x
、height
和width
中的每一个都可以是应用于所有条形的标量,也可以是长度为N
的序列,为每个条形提供单独的值。
在这种情况下,x
和 height
是值序列(每个条形图不同),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 文件创建混合图表的主要内容,如果未能解决你的问题,请参考以下文章
我可以在 python3 中从 excel 文件(不是 CSV)创建字典吗?