我在解析用其他程序创建的文本文件时遇到问题。文本文件看起来像这样:
velocity 4
0 0
0.0800284750334461 0.0702333599787275
0.153911082737118 0.128537103048848
0.222539323234924 0.176328826156044
0.286621942300277 0.21464146333504
0.346732028739683 0.244229944930359
0.403339781262399 0.265638972071027
...
velocity 8
0 0
0.169153136373962 0.124121036173475
0.312016311613761 0.226778846267302
0.435889653693839 0.312371513797743
0.545354054604357 0.383832483710643
0.643486956562741 0.443203331839287
...
我想抓取与速度(标题)同一行的数字,并将其保存为后续数据图的标题。除标题之外的每隔一行代表射击球的 x 和 y 坐标。
因此,如果我有五个不同的标题,我希望在单个图表上看到五个不同的线条,并用图例显示不同的速度。
这是到目前为止我的 python 代码。我已经接近我想要的结果,但我缺少第一组数据(速度 = 4 m/s),并且图例上的颜色与线条颜色不匹配。
import matplotlib.pyplot as plt
xPoints = []
yPoints = []
fig, ax = plt.subplots()
with open('artilleryMotion.txt') as inf:
for line in inf:
column = line.split()
if line.startswith("v"):
velocity = column[1]
ax.plot(xPoints, yPoints, label = '%s m/s' % velocity)
else:
xPoints.append(column[0])
yPoints.append(column[1])
ax.legend()
plt.title("Ping-Pong Ball Artillery Motion")
plt.xlabel("distance")
plt.ylabel("height")
plt.ylim(ymin = 0)
ax.set_autoscaley_on(1)
我已经为此苦苦挣扎了一段时间。
Edit_1:这是我目前的输出:
Edit_2:我删除了最后几行代码的缩进。颜色问题仍然出现。
Edit_3:我如何将每个速度的 x 和 y 点保存到新数组中?这可能会解决我的问题。
Edit_4:感谢 Charles Morris,我能够创建这些图。我现在只需要确定乒乓球在较高速度下的初始向上“弧形”运动是否代表物理现象,或者是我的代码的限制。
最佳答案
编辑:忽略旧信息,并查看下面已解决的解决方案:
以下代码适用于示例文本文件:input.txt
velocity 4
0 0
0.0800284750334461 0.0702333599787275
0.153911082737118 0.128537103048848
0.222539323234924 0.176328826156044
0.286621942300277 0.21464146333504
0.346732028739683 0.244229944930359
0.403339781262399 0.265638972071027
velocity 8
0 0
0.169153136373962 0.124121036173475
0.312016311613761 0.226778846267302
0.435889653693839 0.312371513797743
0.545354054604357 0.383832483710643
0.643486956562741 0.443203331839287
1) 导入我们的文本文件
我们使用 np.genfromtxt() 进行导入。在这种情况下,我们可以指定dtype = float
。这会导致数字作为“Float”导入,因此字符串(在本例中为“Velocity”)作为 NaN 导入。
来源: https://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html How to use numpy.genfromtxt when first column is string and the remaining columns are numbers?
from matplotlib import pyplot as plt
from itertools import groupby
from numpy import NaN as nan
A = np.genfromtxt('input.txt',dtype=float)
>>>
array([[ nan, 4. ],
[ 0. , 0. ],
[ 0.08002848, 0.07023336],
[ 0.15391108, 0.1285371 ],
[ 0.22253932, 0.17632883],
[ 0.28662194, 0.21464146],
[ 0.34673203, 0.24422994],
[ 0.40333978, 0.26563897],
[ nan, 8. ],
[ 0. , 0. ],
[ 0.16915314, 0.12412104],
[ 0.31201631, 0.22677885],
[ 0.43588965, 0.31237151],
[ 0.54535405, 0.38383248],
[ 0.64348696, 0.44320333]])
2) 对导入的数组进行切片 A
我们可以将这些数组分割成单独的 X
和 Y
数组来表示我们的 X 和 Y 值。在这里阅读 numpy 中的数组切片:https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
在本例中,我们采用索引 = 0 (X) 的所有值和索引 1 (Y) 的所有值:
# x values
# y values
X = A[:,0]
Y = A[:,1]
>>> X = array([ nan, 0. , 0.08002848, 0.15391108, 0.22253932,
0.28662194, 0.34673203, 0.40333978, nan, 0. ,
0.16915314, 0.31201631, 0.43588965, 0.54535405, 0.64348696])
>>> Y = array([ 4. , 0. , 0.07023336, 0.1285371 , 0.17632883,
0.21464146, 0.24422994, 0.26563897, 8. , 0. ,
0.12412104, 0.22677885, 0.31237151, 0.38383248, 0.44320333])
3) 拆分每个速度的数据。
在这里,我们希望将 X 和 Y 值分成每个速度的值。我们的 X 值由 Nan
分隔,Y 值由 4,8,16...
分隔。
因此:对于 x
,我们按 nan
进行分割。 nan
是 genfromtxt() 将 Velocity
解析为 float 并返回 nan
的结果。
来源: numpy: split 1D array of chunks separated by nans into a list of the chunks Split array at value in numpy
对于 y
,我们将数组按照数字 4,8,16
等进行拆分。为此,我们排除了除以 4 后得到的值余数为零(使用 %
Python 运算符)。
来源: Split array at value in numpy How to check if a float value is a whole number Split NumPy array according to values in the array (a condition) Find the division remainder of a number How do I use Python's itertools.groupby()?
XX = [list(v) for k,v in groupby(X,np.isfinite) if k]
YY = [list(v) for k,v in groupby(Y,lambda x: x % 4 != 0 or x == 0) if k]
>>>
XX = [[0.0,
0.080028475033446095,
0.15391108273711801,
0.22253932323492401,
0.28662194230027699
0.34673202873968301,
0.403339781262399],
[0.0,
0.16915313637396201,
0.31201631161376098,
0.43588965369383897,
0.54535405460435704,
0.64348695656274102]]
>>> YY =
[[0.0,
0.070233359978727497,
0.12853710304884799,
0.17632882615604401,
0.21464146333504,
0.24422994493035899,
0.26563897207102699],
[0.0,
0.124121036173475,
0.22677884626730199,
0.31237151379774297,
0.38383248371064299,
0.44320333183928701]]
4)提取标签
使用与上面类似的技术,我们接受值=我们的速度4,8,16
等。在这种情况下,我们只接受那些除以4时余数为0的数字、 和 都不为 0。然后我们将其转换为字符串并添加 m/s
。
Ylabels = [list(v) for k,v in groupby(Y,lambda x: x % 4 == 0 and x != 0) if k]
Velocities = [str(i[0]) + ' m/s' for i in Ylabels]
>>> Y labels = [[4.0], [8.0]]
>>> Velocities = ['4.0 m/s', '8.0 m/s']
5) 绘图
按索引绘制每个速度的值。
fig, ax = plt.subplots()
for i in range(0,len(XX)):
plt.plot(XX[i],YY[i],label = Velocities[i])
ax.legend()
plt.title("Ping-Pong Ball Artillery Motion")
plt.xlabel("distance")
plt.ylabel("height")
plt.ylim(ymin = 0)
ax.set_autoscaley_on(1)
代码总计:
import numpy as np
from matplotlib import pyplot as plt
from itertools import groupby
from numpy import NaN as nan
A = np.genfromtxt('input.txt',dtype=float)
X = A[:,0]
Y = A[:,1]
Ylabels = [list(v) for k,v in groupby(Y,lambda x: x % 4 == 0 and x != 0) if k]
Velocities = [str(i[0]) + ' m/s' for i in Ylabels]
XX = [list(v) for k,v in groupby(X,np.isfinite) if k]
YY = [list(v) for k,v in groupby(Y,lambda x: x % 4 != 0 or x == 0) if k]
fig, ax = plt.subplots()
for i in range(0,len(XX)):
plt.plot(XX[i],YY[i],label = Velocities[i])
ax.legend()
plt.title("Ping-Pong Ball Artillery Motion")
plt.xlabel("distance")
plt.ylabel("height")
plt.ylim(ymin = 0)
ax.set_autoscaley_on(1)
旧答案:
第一次迭代文件中的所有行时,xPoints
和 yPoints
数组为空。因此,当您尝试绘制 v = 4 的值时,您正在绘制一个空数组 - 因此您丢失了一行。
您需要先填充数组,然后绘制它们。目前,您正在标记为 v = 8 的行中绘制 v = 4 的值,对于 v = 8,绘制 v = 16 的值,依此类推。
忽略: 对于数组总体,请尝试以下操作:
xPoints = []
yPoints = []
with open('artilleryMotion.txt') as inf:
# initialize placeholder velocity variable
velocity = 0
for line in inf:
column = line.split()
if line.startswith("v"):
velocity = column[1]
else:
xPoints.append({velocity: column[0]})
yPoints.append({velocity: column[1]})
在上面,您将数据保存为字典列表(x和y点分开),其中键等于最近读取的速度,值是x和y坐标.
当读入新的速度时,占位符变量 velocity
会更新,因此可以根据 x 和 y 值所拥有的键来识别它们。
这允许您通过字典键分离绘图(查找 D.iteritems() D.items() ),并且您可以单独绘制每组点。
关于python - 在文本文件中记录标题并用后续数据绘制图表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42044498/