将丑陋的csv解析为数据帧的最佳方法

2024-09-29 19:33:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我的目的是将Matlab代码移植到Python代码中。 我是python新手,但我仍在尝试分离csv文件

我的目的是解析一个具有类似以下结构的CSV文件:

SENSORID;DATESMPL;TRE;ISRC
FQBI-000-001;08/01/2020 13:56:00;-10.0956;0.03662119
LAMBDAS;1550;1551;1552;1553;1554
REFERENCE;6961.058824;6959.564706;6959.423529;6960.988235;6961.788235
1;166;164;162;138;162
2;146;152;161;143;142
3;138;147;150;133;124
4;134;120;158;145;133
5;135;157;135;139;137

预期结果(在python数据帧上):

    SENSORID         DATESMPL           TRE       ISRC     1550  1551  1552  1553  1554
0 FQBI-000-001  08/01/2020 13:56:00  -10.0956  0.03662119   166  164   162   138   162
1 FQBI-000-001  08/01/2020 13:56:00  -10.0956  0.03662119   146  152   161   143   142
2 FQBI-000-001  08/01/2020 13:56:00  -10.0956  0.03662119   138  147   150   133   124
3 FQBI-000-001  08/01/2020 13:56:00  -10.0956  0.03662119   134  120   158   145   133
4 FQBI-000-001  08/01/2020 13:56:00  -10.0956  0.03662119   135  157   135   139   137

参考行将被丢弃。 传感器ID、DATESMPL、TRE和ISRC的值必须为每个实际测量数据行(从1到5的整数开始)复制

当然,我必须解析的实际CSV比我的示例中要大得多,即LAMBDA从1550到1850,有255个测量行(每个文件大约250 kB)

为了让事情变得更简单,我最终将不得不导入多达10000个这些文件,并将它们存储在一个唯一的DataFrame

使用Matlab,我可以使用textscan函数解析这些文件,并将数据存储在统计工具箱提供的dataset对象中。导入10000个文件可以在不到10分钟的时间内完成,这在本案例中是可以接受的

在Python下,最好的方法是什么?

似乎有很多方法可以做到这一点:

  • 将文件内容作为列表中的字符串读取
  • 使用NumPy数组或
  • 使用DataFrame.read_csv()

但我不确定什么是最有效的方法

我真的很想保持性能接近(或者更好,当然)我与Matlab


Tags: 文件csv数据方法代码目的dataframetre
2条回答

您需要对文件进行两次解析:一次用于获取元数据,另一次用于获取数据。然后将两个数据帧连接在一起:

path = '/path/to/file.txt'
meta = pd.read_csv(path, sep=';', nrows=1)
data = pd.read_csv(path, sep=';', skiprows=[0,1,3]).drop(columns='LAMBDAS')

# Limit the `fillna` to the columns in `meta`
df = pd.concat([meta, data], axis=1)
df[meta.columns] = df[meta.columns].fillna(method='ffill')

# If you are sure `data` has no NaN
df = pd.concat([meta, data], axis=1).fillna(method='ffill')

我想投入我的两分钱作为更快的解决方案,因为您提到性能很重要。与Code_Different的解决方案相比,该方法的执行速度约为每个文件的5-10倍。使用数据示例-如何处理更大的文件,您必须测试自己

def parse(file):
       columns = []
       #general_values = [] # use this if the meta data columns are different
       column_values = ['SENSORID', 'DATESMPL', 'TRE', 'ISRC']
       measurement_values = []

       with open('tmp.csv', "r") as f:
              for index, row in enumerate(f):
                     if index > 3:  # test for measurement rows first as you will do it most often
                            measurement_values.append(row[:-1].split(';')[1:])
                     # uncomment next elif-clause if the meta data column names differ per file
                     #elif index == 0:  # first row -> SENSORID;DATESMPL;TRE;ISRC
                     #       columns += row[:-1].split(';')  # get rid of newline and split
                     elif index == 1:  # second row -> meta data
                            general_values = row[:-1].split(';') # get rid of newline and split
                     elif index == 2:  # fourth row  -> Lambdas as column names
                            columns += row[:-1].split(';')[1:]  # get rid of newline, split and delete 'LAMBDAS'

       df_array = [columns]
       for measurement in measurement_values:
              df_array.append(general_values + measurement)
       return pd.DataFrame(df_array)

df = parse('tmp.csv')

相关问题 更多 >

    热门问题