gpt4 book ai didi

python - 如何从 csv 文件制作稀疏 pandas DataFrame

转载 作者:行者123 更新时间:2023-12-04 14:02:08 25 4
gpt4 key购买 nike

我有一个相当大(1.3 GB,未压缩)的 csv 文件,包含 2 个密集列和 1.4 K 稀疏列,大约 1 M 行。

我需要从中制作一个 pandas.DataFrame。

对于小文件我可以简单地做:

df = pd.read_csv('file.csv')

对于我现在拥有的大文件,出现内存错误,这显然是由于 DataFrame 大小(通过 sys.getsizeof(df)

测试)

基于这份文件:

https://pandas.pydata.org/pandas-docs/stable/user_guide/sparse.html#migrating

看起来我可以制作一个包含密集列和稀疏列的 DataFrame。

但是,我只能从 csv 文件中看到添加单个稀疏列的说明,而不是所有这些列的一大块。

逐一读取 csv 稀疏列并将它们添加到 df 使用:

for colname_i in names_of_sparse_columns:
data = pd.read_csv('file.csv', usecols = [colname_i])
df[colname_i] = pd.arrays.SparseArray(data.values.transpose()[0])

有效,并且 df 保持非常小,如预期的那样,但执行时间长得离谱。

我当然试过了:

pd.read_csv(path_to_input_csv, usecols = names_of_sparse_columns, dtype = "Sparse[float]")

但是会产生这个错误:

NotImplementedError: Extension Array: <class 'pandas.core.arrays.sparse.array.SparseArray'> must implement _from_sequence_of_strings in order to be used in parser methods

Any idea how I can do this more efficiently?

我检查了几个帖子,但它们似乎都在追求与此略有不同的东西。


编辑 添加一个小例子,以澄清

import numpy as np
import pandas as pd
import sys

# Create an unpivoted sparse dataset
lengths = list(np.random.randint(low = 1, high = 5, size = 10000))
cols = []
for l in lengths:
cols.extend(list(np.random.choice(100, size = l, replace = False)))
rows = np.repeat(np.arange(10000), lengths)
vals = np.repeat(1, sum(lengths))
df_unpivoted = pd.DataFrame({"row" : rows, "col" : cols, "val" : vals})

# Pivot and save to a csv file
df = df_unpivoted.pivot(index = "row", columns = "col", values = "val")
df.to_csv("sparse.csv", index = False)

此文件在我的电脑上占用 1 MB。
相反:

sys.getsizeof(df)
# 8080016

这对我来说看起来像 8 MB。
因此,当从稀疏 csv 文件制作 pd.DataFrame 时,大小明显增加了很多(在这种情况下,我从数据框制作文件,但它与读取 csv 文件相同使用 pd.read_csv())。

这就是我的观点:我不能使用pd.read_csv()整个 csv 文件加载到内存中。
这里只有8MB,完全没有问题;对于我提到的实际 1.3 GB csv,它的大小如此之大,以至于使我们的机器内存崩溃。
我想这很容易尝试,在上面的模拟中将 10000 替换为 1000000,将 100 替换为 1500。

如果我这样做:

names_of_sparse_columns = df.columns.values

df_sparse = pd.DataFrame()

for colname_i in names_of_sparse_columns:
data = pd.read_csv('sparse.csv', usecols = [colname_i])
df_sparse[colname_i] = pd.arrays.SparseArray(data.values.transpose()[0])

生成的对象要小得多:

sys.getsizeof(df_sparse)
# 416700

实际上比文件还要小。

这是我的第二点:逐列添加稀疏列非常慢。

I was looking for advice on how to make df_sparse from a file like "sparse.csv" faster / more efficiently.

事实上,当我写这个例子的时候,我注意到:

sys.getsizeof(df_unpivoted)
# 399504

所以也许解决方案是逐行读取 csv 文件并将其取消透视。然而,我需要做的其余处理仍然需要我写出一个旋转的 csv,所以回到原点。


编辑 2 更多信息

我也描述了我需要做的其余处理。

当我可以使用非稀疏数据框时,文件中有一个ID列:

df["ID"] = list(np.random.choice(20, df.shape[0]))

我需要总结每个数据列的每个 ID 存在多少数据:

df.groupby("ID").count()

不幸的是稀疏数据框不支持这个。
我找到了一个解决方法,但它非常低效且缓慢。

If anyone can advise on that aspect, too, it would be useful.

我猜想会有一种方法可以将 csv 的稀疏部分加载到某种形式的稀疏数组中,并通过 ID 进行汇总。

也许我完全以错误的方式处理这个问题,这就是为什么我向广大有能力的观众征求意见的原因。

最佳答案

我完全不知道为什么有人会制作那种格式的 CSV。我会把它作为 block 读入并修复 block 。

# Read in chunks of data, melt it into an dataframe that makes sense
data = [c.melt(id_vars=dense_columns, var_name="Column_label", value_name="Thing").dropna()
for c in pd.read_csv('file.csv', iterator=True, chunksize=100000)]

# Concat the data together
data = pd.concat(data, axis=0)

根据需要更改 block 大小和值列的名称。如果需要,您也可以分块读取并将这些 block 转换为稀疏数据帧,但似乎您最好使用融化的数据帧来完成您想要做的事情,IMO。

您也可以随时以其他方式再次分块。根据数据需要更改 block 数。

with open('out_file.csv', mode='w') as out:

for i, chunk in enumerate(np.array_split(df, 100)):

chunk.iloc[:, 2:] = chunk.iloc[:, 2:].sparse.to_dense()
chunk.to_csv(out, header=i==0)

关于python - 如何从 csv 文件制作稀疏 pandas DataFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69646380/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com