pandas 从 matplotlib 中的 .CSV 文件制作多线图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16568964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Make a multiline plot from .CSV file in matplotlib
提问by user2324693
I've been trying for weeks to plot 3 sets of (x, y) data on the same plot from a .CSV file, and I'm getting nowhere. My data was originally an Excel file which I have converted to a .CSV file and have used pandas
to read it into IPython as per the following code:
我一直在尝试从 .CSV 文件在同一个图上绘制 3 组 (x, y) 数据,但一无所获。我的数据最初是一个 Excel 文件,我已将其转换为 .CSV 文件,并已pandas
按照以下代码将其读入 IPython:
from pandas import DataFrame, read_csv
import pandas as pd
# define data location
df = read_csv(Location)
df[['LimMag1.3', 'ExpTime1.3', 'LimMag2.0', 'ExpTime2.0', 'LimMag2.5','ExpTime2.5']][:7]
My data is in the following format:
我的数据格式如下:
Type mag1 time1 mag2 time2 mag3 time3
M0 8.87 41.11 8.41 41.11 8.16 65.78;
...
M6 13.95 4392.03 14.41 10395.13 14.66 25988.32
I'm trying to plot time1
vs mag1
, time2
vs mag2
and time3
vs mag3
, all on the same plot, but instead I get plots of time..
vs Type
, eg. for the code:
我试图在同一个图上绘制time1
vs mag1
、time2
vsmag2
和time3
vs mag3
,但是我得到了time..
vs 的图Type
,例如。对于代码:
df['ExpTime1.3'].plot()
I get 'ExpTime1.3'
(y-axis) plotted against M0
to M6
(x-axis), when what I want is 'ExpTime1.3'
vs 'LimMag1.3'
, with x-labels M0
- M6
.
当我想要的是vs 时,我将'ExpTime1.3'
(y 轴) 绘制M0
为M6
(x 轴) ,带有 x 标签- 。'ExpTime1.3'
'LimMag1.3'
M0
M6
How do I get
'ExpTime..'
vs'LimMag..'
plots, with all 3 sets of data on the same plot?How do I get the
M0
-M6
labels on the x-axis for the'LimMag..'
values (also on the x-axis)?
我如何获得
'ExpTime..'
vs'LimMag..'
绘图,所有 3 组数据都在同一个绘图上?如何在 x 轴上获取值的
M0
-M6
标签'LimMag..'
(也在 x 轴上)?
Since trying askewchan's solutions, which did not return any plots for reasons unknown, I've found that I can get a plot of ExpTime
vs LimMag
using df['ExpTime1.3'].plot(),
if I change the dataframe index (df.index) to the values of the x axis (LimMag1.3). However, this appears to mean that I have to convert each desired x-axis to the dataframe index by manually inputing all the values of the desired x-axis to make it the data index. I have an awful lot of data, and this method is just too slow, and I can only plot one set of data at a time, when I need to plot all 3 series for each dataset on the one graph. Is there a way around this problem? Or can someone offer a reason, and a solution, as to why I I got no plots whatsoever with the solutions offered by askewchan?\
自从尝试了 askewchan 的解决方案,由于未知原因没有返回任何图,我发现如果我将数据帧索引(df.index)更改为 x 轴的值(LimMag1.3),我可以得到一个ExpTime
vsLimMag
使用的图df['ExpTime1.3'].plot(),
)。但是,这似乎意味着我必须通过手动输入所需 x 轴的所有值来将每个所需的 x 轴转换为数据帧索引,以使其成为数据索引。我有大量的数据,这种方法太慢了,我一次只能绘制一组数据,当我需要在一个图表上绘制每个数据集的所有 3 个系列时。有没有办法解决这个问题?或者有人可以提供一个原因和解决方案,为什么 II 没有得到 askewchan 提供的解决方案的任何情节?\
In response to nordev, I have tried the first version again, bu no plots are produced, not even an empty figure. Each time I put in one of the ax.plot
commands, I do get an output of the type:
[<matplotlib.lines.Line2D at 0xb5187b8>]
, but when I enter the command plt.show()
nothing happens.
When I enter plt.show()
after the loop in askewchan's second solution, I get an error back saying AttributeError: 'function' object has no attribute 'show'
响应nordev,我又试了第一个版本,没有产生任何情节,甚至没有一个空图。每次我输入其中一个ax.plot
命令时,我都会得到一个类型为: 的输出
[<matplotlib.lines.Line2D at 0xb5187b8>]
,但是当我输入命令时plt.show()
什么也没有发生。当我plt.show()
在 askewchan 的第二个解决方案的循环之后进入时,我收到一条错误消息AttributeError: 'function' object has no attribute 'show'
I have done a bit more fiddling with my original code and can now get a plot of ExpTime1.3
vs LimMag1.3
with the code df['ExpTime1.3'][:7].plot()
,by making the index the same as the x axis (LimMag1.3), but I can't get the other two sets of data on the same plot. I would appreciate any further suggestions you may have. I'm using ipython 0.11.0 via Anaconda 1.5.0 (64bit) and spyder on Windows 7 (64bit), python version is 2.7.4.
我对我的原始代码做了更多的修改,现在可以通过使索引与 x 轴 (LimMag1.3) 相同来获得带有代码的ExpTime1.3
vs的图,但我无法获得其他两组同一地块上的数据。如果您有任何进一步的建议,我将不胜感激。我在 Windows 7(64 位)上通过 Anaconda 1.5.0(64 位)和 spyder 使用 ipython 0.11.0,python 版本是 2.7.4。LimMag1.3
df['ExpTime1.3'][:7].plot()
回答by sodd
If I have understood you correctly, both from this question as well as your previous one on the same subject, the following should be basic solutions you could customize to your needs.
如果我从这个问题以及您之前关于同一主题的问题中都正确理解了您,那么以下应该是您可以根据需要自定义的基本解决方案。
Several subplots:
几个子图:
Note that this solution will output as many subplots as there are Spectral classes (M0, M1, ...) vertically on the same figure. If you wish to savethe plot of each Spectral class in a separate figure, the code needs some modifications.
请注意,此解决方案将输出与同一图上垂直的光谱类(M0、M1...)一样多的子图。如果您希望将每个 Spectral 类的图保存在单独的图形中,则需要对代码进行一些修改。
import pandas as pd
from pandas import DataFrame, read_csv
import numpy as np
import matplotlib.pyplot as plt
# Here you put your code to read the CSV-file into a DataFrame df
plt.figure(figsize=(7,5)) # Set the size of your figure, customize for more subplots
for i in range(len(df)):
xs = np.array(df[df.columns[0::2]])[i] # Use values from odd numbered columns as x-values
ys = np.array(df[df.columns[1::2]])[i] # Use values from even numbered columns as y-values
plt.subplot(len(df), 1, i+1)
plt.plot(xs, ys, marker='o') # Plot circle markers with a line connecting the points
for j in range(len(xs)):
plt.annotate(df.columns[0::2][j][-3:] + '"', # Annotate every plotted point with last three characters of the column-label
xy = (xs[j],ys[j]),
xytext = (0, 5),
textcoords = 'offset points',
va = 'bottom',
ha = 'center',
clip_on = True)
plt.title('Spectral class ' + df.index[i])
plt.xlabel('Limiting Magnitude')
plt.ylabel('Exposure Time')
plt.grid(alpha=0.4)
plt.tight_layout()
plt.show()
All in same Axes, grouped by rows (M0, M1, ...)
所有在相同的轴,按行分组(M0,M1,...)
Here is another solution to get all the different Spectral classes plotted in the same Axes with a legend identifying the different classes. The plt.yscale('log')
is optional, but seeing as how the values span such a great range, it is recommended.
这是另一个解决方案,用于将所有不同的 Spectral 类绘制在相同的 Axes 中,并带有标识不同类的图例。该plt.yscale('log')
是可选的,但看到该值是如何跨越这么大的范围内,值得推荐。
import pandas as pd
from pandas import DataFrame, read_csv
import numpy as np
import matplotlib.pyplot as plt
# Here you put your code to read the CSV-file into a DataFrame df
for i in range(len(df)):
xs = np.array(df[df.columns[0::2]])[i] # Use values from odd numbered columns as x-values
ys = np.array(df[df.columns[1::2]])[i] # Use values from even numbered columns as y-values
plt.plot(xs, ys, marker='o', label=df.index[i])
for j in range(len(xs)):
plt.annotate(df.columns[0::2][j][-3:] + '"', # Annotate every plotted point with last three characters of the column-label
xy = (xs[j],ys[j]),
xytext = (0, 6),
textcoords = 'offset points',
va = 'bottom',
ha = 'center',
rotation = 90,
clip_on = True)
plt.title('Spectral classes')
plt.xlabel('Limiting Magnitude')
plt.ylabel('Exposure Time')
plt.grid(alpha=0.4)
plt.yscale('log')
plt.legend(loc='best', title='Spectral classes')
plt.show()
All in same Axes, grouped by columns (1.3", 2.0", 2.5")
全部在相同的轴中,按列(1.3"、2.0"、2.5")分组
A third solution is as shown below, where the data are grouped by the series (columns 1.3", 2.0", 2.5") rather than by the Spectral class (M0, M1, ...). This example is very similar to @askewchan's solution. One difference is that the y-axis here is a logarithmic axis, making the lines pretty much parallel.
第三种解决方案如下所示,其中数据按系列(列 1.3"、2.0"、2.5")而不是按 Spectral 类(M0、M1、...)进行分组。此示例与 @ 非常相似askewchan 的解决方案。一个区别是这里的 y 轴是一个对数轴,使线几乎平行。
import pandas as pd
from pandas import DataFrame, read_csv
import numpy as np
import matplotlib.pyplot as plt
# Here you put your code to read the CSV-file into a DataFrame df
xs = np.array(df[df.columns[0::2]]) # Use values from odd numbered columns as x-values
ys = np.array(df[df.columns[1::2]]) # Use values from even numbered columns as y-values
for i in range(df.shape[1]/2):
plt.plot(xs[:,i], ys[:,i], marker='o', label=df.columns[0::2][i][-3:]+'"')
for j in range(len(xs[:,i])):
plt.annotate(df.index[j], # Annotate every plotted point with its Spectral class
xy = (xs[:,i][j],ys[:,i][j]),
xytext = (0, -6),
textcoords = 'offset points',
va = 'top',
ha = 'center',
clip_on = True)
plt.title('Spectral classes')
plt.xlabel('Limiting Magnitude')
plt.ylabel('Exposure Time')
plt.grid(alpha=0.4)
plt.yscale('log')
plt.legend(loc='best', title='Series')
plt.show()
回答by askewchan
You can call pyplot.plot(time, mag)
three different times in the same figure. It would be wise to give a label to them. Something like this:
您可以pyplot.plot(time, mag)
在同一图中调用三个不同的时间。给他们贴上标签是明智的。像这样的东西:
import matplotlib.pyplot as plt
...
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(df['LimMag1.3'], df['ExpTime1.3'], label="1.3")
ax.plot(df['LimMag2.0'], df['ExpTime2.0'], label="2.0")
ax.plot(df['LimMag2.5'], df['ExpTime2.5'], label="2.5")
plt.show()
If you want to loop it, this would work:
如果你想循环它,这将工作:
fig = plt.figure()
ax = fig.add_subplot(111)
for x,y in [['LimMag1.3', 'ExpTime1.3'],['LimMag2.0', 'ExpTime2.0'], ['LimMag2.5','ExpTime2.5']]:
ax.plot(df[x], df[y], label=y)
plt.show()