【问题标题】:Best way to parse ugly csv into Pandas DataFrame将丑陋的 csv 解析为 Pandas DataFrame 的最佳方法
【发布时间】:2020-04-26 01:41:26
【问题描述】:

我的目的是将 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 DataFrame 上):

    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

Reference 行将被丢弃。 SENSORID、DATESMPL、TRE 和 ISRC 的值必须为每个实际测量数据行(以 1 到 5 的整数开头)重复。

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

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

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

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

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

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

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

我真的很想保持性能接近(或更好,当然)我在 Matlab 中的表现。

【问题讨论】:

  • 请分享您使用了什么代码,结果如何? pd.read_csv() 很有活力,或许能帮到你
  • 令人印象深刻的是,matlab 可以在没有任何前置条件的情况下处理这样的 csv,每个文件是否包含单个 lambdasfqbireference 或多个?
  • @Datanovice:对不起,如果这是误导,我在 Matlab 下使用 textscan,但我需要 4 个调用和它们之间的一些处理。第一次调用是获取标题的第一行(SENSORID,...),第二次调用相关信息(FQBI-000-001,...),第三次调用获取 lambda 列表(1550,...)和最后调用以读取所有剩余行(实际测量行)
  • 读取 csv 文件是问题的一部分。另一部分是如何处理 10000 个文件并避免在构建一个唯一的 DataFrame 时复制数据。所有文件的 LAMBDAS 行是否相同?是否所有数据行都包含 255 个测量值?

标签: python pandas csv dataframe parsing


【解决方案1】:

正如您提到的性能很重要,我想投入两分钱作为更快的解决方案。与 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')

【讨论】:

    【解决方案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')
    

    【讨论】:

      猜你喜欢
      • 2023-02-01
      • 2011-09-15
      • 1970-01-01
      • 2018-05-18
      • 2018-06-11
      • 2011-05-03
      • 1970-01-01
      • 2010-10-02
      • 1970-01-01
      相关资源
      最近更新 更多