【问题标题】:Is it possible to parse csv columns containing arrays with vectorized Pandas code?是否可以使用矢量化 Pandas 代码解析包含数组的 csv 列?
【发布时间】:2020-02-04 20:49:52
【问题描述】:

以下代码生成一个 CSV,然后再次对其进行解析。 b 列包含每个字段的整数数组。

import pandas as pd
from io import StringIO
import numpy as np


# Create CSV
df = pd.DataFrame(dict(
    a=[1,2,3],
    b=[[1], [1,2], [1,2,3]]
))
s = df.to_csv()

# ,a,b
# 0,1,[1]
# 1,2,"[1, 2]"
# 2,3,"[1, 2, 3]"

def parse(s):
    return np.fromstring(s[1:-1], sep=", ", dtype=int)

df2 = pd.read_csv(StringIO(s), converters=dict(b=parse))

现在的问题是是否可以矢量化/加速解析。我怀疑这可能通过为 b 列指定 dtype 来实现,但我无法弄清楚这将是什么 dtype。

有什么建议吗?

【问题讨论】:

  • .csv 的要求吗?如果你想要 I/O 操作之间的对象持久性,有更好的文件格式可以存储 python 对象。
  • 我目前使用 CSV 的原因是因为我可以轻松地附加到它(逐行)并从各种编程语言(python、c++、node、java)中读取它。但是,我想测试是否可以改用镶木地板。但是我猜 parquet 并没有真正针对附加用例进行优化。您会推荐其他格式吗?
  • 我刚刚运行了一些测试并且附加到 Parquet 会导致更大的文件。此外,节点没有官方 Parquet 编写器。
  • 啊,我主要想知道是否一切都完全在 python 中。既然不是这样,像.pkl 这样的东西可能不值得。

标签: python pandas numpy csv


【解决方案1】:

这个转换器工作吗?那我建议坚持下去。

原始 DF 有一个 object dtype 列,其中包含不同大小的列表。保存写入这些列表的str 版本。你的转换产生一个数组

In [155]: np.fromstring("[1,2,3]"[1:-1], sep=", ", dtype=int)                                  
Out[155]: array([1, 2, 3])

eval(或“更安全”的ast 等效项)生成一个列表:

In [156]: eval("[1, 2, 3]")                                                                    
Out[156]: [1, 2, 3]

请注意,如果原始文件包含数组而不是列表,则字符串将无法正常工作。

In [157]: str(_155)                                                                            
Out[157]: '[1 2 3]'

它缺少方便的逗号。更糟糕的是,它可能包含...,因为数组足够大。

这种情况经常出现,通常是因为人们无意中保存了包含这些列表或数组元素的框架。到目前为止,我还没有看到一个很好的选择——至少如果你想要一个人类可读的 csv 的话。

在某种程度上,具有列表或数组元素的数据框是一种异常。列 dtype 将是 object,并且无法进行快速 numpy 操作。但是 pandas 也对字符串使用对象 dtype。

同样对于长度不同的列表,你不能创建一个 n-d 数组。它只能是列表或对象 dtype 数组。数值数组的计算速度没了。

【讨论】:

  • 不幸的是,eval/literal_eval 比我的解析慢 6 倍
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 2019-04-28
  • 2021-04-04
  • 2023-03-30
  • 2021-12-15
  • 1970-01-01
  • 2019-10-02
相关资源
最近更新 更多