【问题标题】:Reading file with reverse dict to DataFrame efficiently有效地将具有反向字典的文件读取到DataFrame
【发布时间】:2021-09-24 11:17:46
【问题描述】:

我有一堆具有这种结构的 20MB 文本文件:

{'col-1': ['data-11', 'data-12'], 'col-2': [1, 2], 'col-n': [1, 2]}
{'col-1': ['data-21', 'data-22'], 'col-2': [1, 2], 'col-n': [1, 2]}
{'col-1': ['data-31', 'data-32', 'data-33'], 'col-2': [1, 2, 3], 'col-n': [1, 2, 3]}
...

每行中的记录行数各不相同。

我想读为:

        col-1       col-2   col-n
0       data-11     1       1
1       data-12     2       2
2       data-21     1       1
3       data-22     2       2
4       data-31     1       1
5       data-32     2       2
6       data-33     3       3

我已经准备好这样的代码了:

import ast
import pandas as pd
import itertools

def _eval(line: str):
    ''' Turns: {'col-1': ['data-11', 'data-12'], 'col-2': [1, 2], 'col-n': [1, 2]}
        Into: [{'col-1': 'data-11', 'col-2': 1, 'col-n': 1}, {'col-1': 'data-12', 'col-2': 2, 'col-n': 2}]
    '''
    try:
        v = ast.literal_eval(line.rstrip()) # Reads line to dict
        v = [{k: v[k][i] for k in v} for i in range(len(v['col-n']))] # Revers dict, by splitting them and rejoin
        return v
    
    # In case of file structure error
    except Exception as e:
        print('err', e)
        return []

def read_structure(fp):
    with open(fp) as fh:
        return pd.DataFrame(itertools.chain(*list(map(_eval, fh.readlines()))))

但必须有更好的方法。 使用 itertools 和 map 我已经不到 5 秒了。

我想:

A) 优化循环时刻v = [{k: v[k][i] for k in v} for i in range(len(v['col-n']))]

B) 知道是否已经有可以读取这种结构的 pandas 方法(我已经搜索并尝试了所有具有不同参数的 read_dict 和记录方法)

C) 优化它。

该函数已经在线程中运行,因此多线程/处理不是最好的主意。

【问题讨论】:

  • 您计算过文件 I/O 需要多长时间吗?我认为这可能是您无法通过任何优化摆脱的大量 5s。
  • with open('meas-001') as fh: v = fh.readlines(): 23.3 ms ± 880 µs per loop

标签: python pandas algorithm dataframe dictionary


【解决方案1】:

你能试试下面的代码吗:

v = {k: v for k, v in zip(d.keys(), t)} for t in zip(*d.values())]
return v

【讨论】:

    【解决方案2】:

    首先,我会尽量避免readlines 将整个文件作为行列表加载到内存中。然后我会尝试为 Dataframe 构造函数提供一个列表字典:

    def read_structure(fp):
        cols = 'col-1', 'col-2', 'col-n'  # declare the column names
        data = {col: [] for col in cols}  # initialize the data structure
    
        with open(fp) as fh:
            for i, line in enumerate(io.StringIO(t), 1):
                try:
                    row = ast.literal_eval(line)
                    for k, v in row.items():
                        data[k].extend(v)
                except Exception as e:
                    print('Error line', i, line, e)
                    raise           # unsure that we can continue after an error
        return pd.DataFrame(data)
    

    不确定是否快,但至少简单

    【讨论】:

      猜你喜欢
      • 2016-01-31
      • 2019-08-06
      • 1970-01-01
      • 2013-09-28
      • 2018-06-22
      • 2016-02-16
      • 1970-01-01
      • 2019-06-26
      • 2022-01-05
      相关资源
      最近更新 更多