Skip to main content
 首页 » 编程设计

python之使用 python 解析 CSV 文件并转换为 Pandas Dataframe 以绘制 Django 模板的图形

2024年10月25日34zhujiabin

我正在开发一个 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) 

给我: