python - 有没有一种快速的方法可以将 Pandas 的列数据框转换为字符串列表?
问题描述
这在某种程度上与大多数人在列表和数据框之间转换时想做的事情相反。
我希望将大型数据帧(10M+ 行,20+ 列)转换为字符串列表,其中每个条目都是数据帧中每一行的字符串表示形式。我可以使用 pandas 的to_csv()
方法来做到这一点,但我想知道是否有更快的方法,因为这被证明是我的代码中的一个瓶颈。
最小工作示例:
import numpy as np
import pandas as pd
# Create the initial dataframe.
size = 10000000
cols = list('abcdefghijklmnopqrstuvwxyz')
df = pd.DataFrame()
for col in cols:
df[col] = np.arange(size)
df[col] = "%s_" % col + df[col].astype(str)
# Convert to the required list structure
ret_val = _df_.to_csv(index=False, header=False).split("\n")[:-1]
对于我的 Core i9 的单个线程上的 10,000,000 行数据帧,上述代码的转换方面大约需要 90 秒,并且高度依赖于 CPU。如果可能的话,我希望将其降低一个数量级。
编辑:我不想将数据保存到 .csv 或文件中。我只是想将数据框转换为字符串数组。
编辑:只有 5 列的输入/输出示例:
In [1]: df.head(10)
Out [1]: a b c d e
0 a_0 b_0 c_0 d_0 e_0
1 a_1 b_1 c_1 d_1 e_1
2 a_2 b_2 c_2 d_2 e_2
3 a_3 b_3 c_3 d_3 e_3
4 a_4 b_4 c_4 d_4 e_4
5 a_5 b_5 c_5 d_5 e_5
6 a_6 b_6 c_6 d_6 e_6
7 a_7 b_7 c_7 d_7 e_7
8 a_8 b_8 c_8 d_8 e_8
9 a_9 b_9 c_9 d_9 e_9
In [2]: ret_val[:10]
Out [2]: ['a_0,b_0,c_0,d_0,e_0',
'a_1,b_1,c_1,d_1,e_1',
'a_2,b_2,c_2,d_2,e_2',
'a_3,b_3,c_3,d_3,e_3',
'a_4,b_4,c_4,d_4,e_4',
'a_5,b_5,c_5,d_5,e_5',
'a_6,b_6,c_6,d_6,e_6',
'a_7,b_7,c_7,d_7,e_7',
'a_8,b_8,c_8,d_8,e_8',
'a_9,b_9,c_9,d_9,e_9']
解决方案
我得到〜2.5倍的加速multiprocessing
......
import multiprocessing
# df from OPs above code available in global scope
def fn(i):
return df[i:i+1000].to_csv(index=False, header=False).split('\n')[:-1]
with multiprocessing.Pool() as pool:
result = []
for a in pool.map(fn, range(0, len(df), 1000)):
result.extend(a)
在我的笔记本电脑上将 1M 行的总时间从 6.8 秒减少到 2.8 秒,因此有望在 i9 CPU 中扩展到更多内核。
这取决于 Unixfork
语义来与子进程共享数据帧,并且显然做了更多的工作,但可能会有所帮助......
使用numpy.savetxt
Massifox 的建议multiprocessing
将其缩短到 2.0 秒,只需map
以下功能:
def fn2(i):
with StringIO() as fd:
np.savetxt(fd, df[i:i+N], fmt='%s', delimiter=',')
return fd.getvalue().split('\n')[:-1]
结果其他方面基本相同
您说“数据框是类中的变量”的评论可以通过多种不同的方式修复。一种简单的方法就是将数据帧传递给Pool
initializer
不会被选择的点(无论如何在Unix下)并将对它的引用存储在某个全局变量中。然后,每个工作进程都可以使用此引用,例如:
def stash_df(df):
global the_df
the_df = df
def fn(i):
with StringIO() as fd:
np.savetxt(fd, the_df[i:i+N], fmt='%s', delimiter=',')
return fd.getvalue().split('\n')[:-1]
with multiprocessing.Pool(initializer=stash_df, initargs=(df,)) as pool:
result = []
for a in pool.map(fn, range(0, len(df), N)):
result.extend(a)
只要每个Pool
都由单个数据框使用,这就可以了
推荐阅读
- android - Kotlin Coroutines,饼图不旋转
- r - 如何根据 R 中的 url 拆分字符行
- arrays - 从c中的函数返回数组时,静态数组声明和指针数组声明有什么区别
- python - 如何检查通过Django中模型类的变量?
- go - 什么是rand的碰撞。阅读
- javascript - 如何修复“无法读取未定义的属性'get'”
- javascript - React/NextJS 错误:元素类型无效:应为字符串或类/函数,但得到:未定义
- flutter - 如何在flutter sqflite上查看SQL结果
- flutter - 有没有办法在颤动中为滑块的拇指和轨迹添加高程或阴影?
- python - 如何在 Python 中解析 SQL 语法、标记 SQL