首页 > 解决方案 > 与 matlab 相比,数据传输到数组的问题和访问数据时的速度很慢

问题描述

我正在尝试将代码从 matlab 移植到 python,我的主要问题是读取文件并将数据转换为数组。在matlab中:

[filename,pathname,~] = uigetfile('*.out');
data{1} = importdata(fullfile(pathname,filename), '\t', 8);
unit = dados{1}.colheaders;
title = strsplit(char(dados{1}.textdata(7,1)));

在蟒蛇中:

import tkinter.filedialog
import numpy as np
def openfile():
    file_path = tkinter.filedialog.askopenfile(mode='r', filetypes=[('','.out')])
    data=np.loadtxt(file_path,delimiter='\t',skiprows=8)
    nrows, ncols = np.shape(data)
    return data, nrows, ncols
data, nrows, ncols = openfile()
print(data[0:5][0])

但是当我尝试访问第一列(时间向量)然后打印这个向量时,我得到了一行的打印。即使我将索引从 [0:5][0] 反转为 [0][0:5] 我也得到了类似的结果。另一个问题是访问文件比在 matlab 中花费的时间要长得多。下面是我试图在 python 中访问的数据示例。

#
Predictions were generated on 07-Jun-2021 at 07:36:56 using OpenFAST, compiled as a 64-bit application using double precision at commit v2.5.0
 linked with  NWTC Subroutine Library; ElastoDyn; InflowWind; AeroDyn; ServoDyn; HydroDyn; MoorDyn (v1.01.02F, 8-Apr-2016)

Description from the FAST input file: IEA 15 MW offshore reference model on UMaine VolturnUS-S semi-submersible floating platform

Time    NcIMUTVxs   NcIMUTVys   NcIMUTVzs   NcIMUTAxs   NcIMUTAys   NcIMUTAzs   NcIMURVxs   NcIMURVys   NcIMURVzs   NcIMURAxs   NcIMURAys   NcIMURAzs
(s) (m/s)   (m/s)   (m/s)   (m/s^2) (m/s^2) (m/s^2) (deg/s) (deg/s) (deg/s) (deg/s^2)   (deg/s^2)   (deg/s^2)
    0.0000   0.000E+00   0.000E+00   0.000E+00  -7.319E-01  -3.911E-01  -1.344E+00   0.000E+00   0.000E+00   0.000E+00   4.008E+00  -1.493E+01   4.163E-01
    0.0250  -1.818E-02  -9.621E-03  -3.261E-02  -6.358E-01  -3.754E-01  -1.210E+00   9.613E-02  -3.609E-01   9.976E-03   3.542E+00  -1.345E+01   3.672E-01
    0.0500  -3.140E-02  -1.845E-02  -5.898E-02  -5.513E-01  -3.181E-01  -9.064E-01   1.709E-01  -6.537E-01   1.772E-02   2.361E+00  -9.933E+00   2.434E-01
    0.0750  -4.459E-02  -2.540E-02  -7.653E-02  -3.923E-01  -2.385E-01  -4.594E-01   2.103E-01  -8.428E-01   2.174E-02   7.456E-01  -4.845E+00   7.446E-02
    0.1000  -5.177E-02  -3.032E-02  -8.156E-02  -2.350E-01  -1.594E-01   5.288E-02   2.078E-01  -8.920E-01   2.140E-02  -9.449E-01   9.618E-01  -1.022E-01

标签: pythonpandasnumpymatlab

解决方案


numpy.loadtxt通常,效率不是很高(numpy 保存/加载最适合二进制格式)。另外,您的代码原样对我不起作用(因为分隔符不是真正的制表符,而是多个空格,我认为 numpy 不支持)。

在你的位置,我会使用原始 python(然后转换为 numpy 数组)或 pandas(可能更慢但更健壮)。

忽略 tkinter 部分并假设文件名是data.txt,第一个解决方案如下所示:

import numpy as np

data = []
with open('data.txt') as fp:
    for i, line in fp:
        if i >= 8:
            data.append([float(x) for x in line.split()])
data = np.asarray(data)

pandas 的第二个解决方案是:

import pandas as pd
df = pd.read_csv('data.txt', skiprows=7, delimiter=' ', skipinitialspace=True)
data = df.values

结果是等价的,但略有不同:python 的split函数会自动修剪开头和结尾的空白,另外它会将任何空白视为一个分隔符(一个空格、多个空格、制表符等)。在您提供的示例中转换为float有效。跳过所有前 8 行。Pandas 的版本也忽略了多个空格,但我认为它不适用于制表符,而且我们需要明确告诉它忽略行首的空格。我们也只是跳过 7 行,而不是 8 行,因为默认情况下 csv 文件必须在第一列中有列名。所以在这种特殊情况下,我们会得到一个带有列名的数据框

['(s)', '(m/s)', '(m/s).1', '(m/s).2', '(m/s^2)', '(m/s^2).1',
       '(m/s^2).2', '(deg/s)', '(deg/s).1', '(deg/s).2', '(deg/s^2)',
       '(deg/s^2).1', '(deg/s^2).2']

但这并不重要,因为当我们最后取.values时,只保留数值。

也许,更重要的区别是,如果在某个地方(例如,字符串)存在无效值,python 的代码会在尝试转换为 float 时引发异常,pandas 的解决方案会很乐意接受它并创建一个 " object”类型(即“anything”类型),甚至不将有效条目转换为浮点数(在该列中)。


推荐阅读