我正在开发一个 Web 应用程序,它允许客户上传 CSV 文件(不幸的是,它几乎遵守零标准),将解析 CSV 以获取适当的数据,然后在 matplotlib 图形中显示数据Pandas DataFrame对象到 Django HTML 模板。
下面是一个可以上传的 CSV 文件示例:
Shock Name,
Shock ID,
Vehicle,
Location,
Compression Valving,
Rebound Valving,
Piston Valving,
Other Valving,
Compression Setting,
Rebound Setting,
Preload Setting,
Notes,
,
,
Measured_Stroke, 2.00 in
Test_Temperature, 79.58 F
Peak_Velocity, 9.98 in/sec
,
Amplitude, 1.00 in
Test_Period, 0.01 sec
Gas_Force, 9.25 lbs
Test_Speed, 1.00 in/sec
Compression Velocity, Compression Force, Rebound Velocity, Rebound Force
in/sec, lbs, in/sec, lbs
-8.373589E-03, 6.810879, -8.373589E-03, 6.810879
-0.9864202, 140.6932, 0.9310969, -170.4664
-1.97424, 158.4015, 1.915599, -388.0251
-2.984882, 171.0502, 2.903838, -410.7928
-3.976808, 178.6395, 3.910722, -425.9714
-4.987449, 186.2288, 4.898961, -441.15
-5.941944, 191.2883, 5.905845, -451.269
-6.952637, 198.8775, 6.894975, -463.9178
-7.963353, 203.937, 7.865953, -474.0368
-8.955353, 208.9965, 8.855605, -486.6855
-9.947352, 214.056, 9.882603, -494.2748
文件顶部的各种变量名称只是生成 CSV 的原始程序保存的设置。相关数据从包括 Compression Velocity, Compression Force, etc... 的行开始,然后一直持续到最后。事实上,绘图所需的唯一真正相关数据是第一列和第二列,即:Compression Force 和 Compression Velocity。标题下方带有单位的行是必需的,因为图表必须采用公制格式,因此在构建图表时,需要转换相应列中的值(例如,“in/sec”到“meters/sec”,等),但不是图表的一部分。
我的想法是扫描 CSV 直到找到 "Compression Velocity" 实例,然后将该行用作 DataFrame 的标题行。我相信我正确地完成了这项工作,但无法正确构建图形。以下是我的尝试:
def graph(request):
pd.set_option('display.mpl_style', 'default')
plt.rcParams['figure.figsize'] = (15,10)
# get filename from sessions id
new_file = request.session.get('docFile')
# Process csv file -->
raw_data = open(new_file, 'rb').read()
rows = re.split('\n', raw_data.decode())
for index, row in enumerate(rows):
cells = row.split(',')
if 'Compression Velocity' in cells: # scan for the string 'Compression Velocity' in csv file read
header_names = cells
header_row = index
break
else:
header_names = {''}
header_row = 0
fig = Figure()
ax = fig.add_subplot(111)
ax.set_xlabel("Velocity")
ax.set_ylabel("Force")
data_df = pd.read_csv(new_file, header=header_row-2)
data_df = pd.DataFrame(data_df)
data_df.plot(ax=ax, title="Roehrig Shock Data", style="-o")
canvas = FigureCanvas(fig)
response = HttpResponse( content_type = 'image/png')
canvas.print_png(response)
return response
在这不起作用之后,我尝试解析 CSV 并将适当的行存储到 NumPy 数组中,然后从该数组构造 DataFrame,但这也不起作用。以下是我的尝试:
raw_data = open(new_file, 'rb').read()
rows = re.split('\n', raw_data.decode())
for index, row in enumerate(rows):
cells = row.split(',')
if 'Compression Velocity' in cells: # scan for the string 'Compression Velocity' in csv file read
header_names = cells
header_row = index
break
else:
header_names = {''}
header_row = 0
useable_data = []
csv_reader = csv.reader(open(new_file, 'r'))
for row in islice(csv_reader, header_row, None):
if 'Compression Velocity' in cells:
useable_data.append(row)
else:
continue
useable_data = np.array(useable_data)
fig = Figure()
ax = fig.add_subplot(111)
ax.set_xlabel("Velocity")
ax.set_ylabel("Force")
data_df = pd.read_csv(new_file, header=header_row)
data_df = pd.DataFrame(useable_data, columns=['Compression Velocity', 'Force'])
data_df = pd.DataFrame.from_csv(new_file, header=header_row, index_col=True)
data_df.plot(ax=ax, title="Roehrig Shock Data", style="-o")
canvas = FigureCanvas(fig)
response = HttpResponse( content_type = 'image/png')
canvas.print_png(response)
return response
我知道很难在没有错误消息的情况下提出关于 SO 的问题,但我的问题是我目前没有任何错误消息可以提供。一切出错都是基于逻辑错误而不是语法错误。如果你能想到一个更好的方法来实现这个目标那么我很乐意听到它,或者如果你能发现明显存在于我上面的代码中的明显错误可以产生一个解决方案那么我会很高兴出色地。感谢您的帮助。
编辑:
我当前的数据框:
-8.373589E-03, 6.810879, -8.373589E-03, 6.810879.1
-0.9864202,140.6932,0.9310969000000001,-170.4664
-1.9742400000000002,158.4015,1.915599,-388.0251
-2.984882,171.0502,2.903838,-410.7928
-3.976808,178.6395,3.9107220000000003,-425.9714
-4.987449,186.2288,4.898961,-441.15
-5.941944,191.2883,5.905844999999999,-451.269
-6.952636999999999,198.8775,6.894975,-463.9178
-7.963353,203.937,7.865953,-474.0368
-8.955353,208.9965,8.855605,-486.6855
-9.947352,214.05599999999998,9.882603,-494.2748
根据 Paul H 的建议,我添加了 skiprows 参数,但由于我跳过了带有单位的行,它似乎也忽略了列标题行。
数据读取
data_df = pd.read_csv(new_file, index_col=0, skiprows=header_row+2) # skip the row with the units
data_df = pd.DataFrame(data_df)
请您参考如下方法:
这是我读取文件的方式:
csv = StringIO("""\
Shock Name,
Shock ID,
Vehicle,
Location,
Compression Valving,
Rebound Valving,
Piston Valving,
Other Valving,
Compression Setting,
Rebound Setting,
Preload Setting,
Notes,
,
,
Measured_Stroke, 2.00 in
Test_Temperature, 79.58 F
Peak_Velocity, 9.98 in/sec
,
Amplitude, 1.00 in
Test_Period, 0.01 sec
Gas_Force, 9.25 lbs
Test_Speed, 1.00 in/sec
Compression Velocity, Compression Force, Rebound Velocity, Rebound Force
in/sec, lbs, in/sec, lbs
-8.373589E-03, 6.810879, -8.373589E-03, 6.810879
-0.9864202, 140.6932, 0.9310969, -170.4664
-1.97424, 158.4015, 1.915599, -388.0251
-2.984882, 171.0502, 2.903838, -410.7928
-3.976808, 178.6395, 3.910722, -425.9714
-4.987449, 186.2288, 4.898961, -441.15
-5.941944, 191.2883, 5.905845, -451.269
-6.952637, 198.8775, 6.894975, -463.9178
-7.963353, 203.937, 7.865953, -474.0368
-8.955353, 208.9965, 8.855605, -486.6855
-9.947352, 214.056, 9.882603, -494.2748
""")
pandas.read_csv(csv, skiprows=24).drop(0, axis=0).astype(float)
.drop(0, axis=0) 删除第二行。 .astype(float) 将所有内容转换为数字。如何确定 skiprows=24 由您决定。
我得到:
Compression Velocity Compression Force Rebound Velocity Rebound Force
1 -8.373589E-03 6.810879 -8.373589E-03 6.810879
2 -0.9864202 140.6932 0.9310969 -170.4664
3 -1.97424 158.4015 1.915599 -388.0251
4 -2.984882 171.0502 2.903838 -410.7928
5 -3.976808 178.6395 3.910722 -425.9714
6 -4.987449 186.2288 4.898961 -441.15
7 -5.941944 191.2883 5.905845 -451.269
8 -6.952637 198.8775 6.894975 -463.9178
9 -7.963353 203.937 7.865953 -474.0368
10 -8.955353 208.9965 8.855605 -486.6855
11 -9.947352 214.056 9.882603 -494.2748
现在:
df['Compression Velocity'].plot(legend=False)
给我:
