python dataframe - lambda X 函数 - 更高效的实现可能吗?
python dataframe - lambda X function - more efficient implementation possible?
在之前的帖子中,对以下问题(Pandas: reshaping data)给出了精彩的回答。
目标是通过以下方式将包含列表的 pandas 系列重塑为 pandas 数据框:
In [9]: s = Series([list('ABC'),list('DEF'),list('ABEF')])
In [10]: s
Out[10]:
0 [A, B, C]
1 [D, E, F]
2 [A, B, E, F]
dtype: object
应该变成这样:
Out[11]:
A B C D E F
0 1 1 1 0 0 0
1 0 0 0 1 1 1
2 1 1 0 0 1 1
也就是说,创建一个数据框,其中系列列表中的每个元素都成为一列。对于系列中的每个元素,都会在数据框中创建一行。对于列表中的每个元素,将 1 分配给相应的数据框列(否则为 0)。我知道措辞可能很繁琐,但希望上面的例子很清楚。
用户 Jeff (https://whosebug.com/users/644898/jeff) 的精彩回应是编写了这行简单而强大的代码:
In [11]: s.apply(lambda x: Series(1,index=x)).fillna(0)
将 [10] 转换为 [11]。
这行代码对我来说非常有用,但是我 运行 遇到了一系列大约 50K 元素和所有列表中大约 100K 不同元素的内存问题。我的机器有16G内存。在求助于更大的机器之前,我想考虑一个更高效的实现上面的功能。
有谁知道如何重新实现上面的行:
In [11]: s.apply(lambda x: Series(1,index=x)).fillna(0)
在内存使用方面提高效率?
您可以尝试将数据帧分成多个块并边写边写入文件,如下所示:
chunksize = 10000
def f(df):
return f.apply(lambda x: Series(1,index=x)).fillna(0)
with open('out.csv','w') as f:
f.write(df.ix[[]].to_csv()) #write the header
for chunk in df.groupby(np.arange(len(df))//chunksize):
f.write(f(chunk).to_csv(header=None))
如果内存使用是问题,那么稀疏矩阵解决方案似乎会更好。 Pandas 并不真正支持稀疏矩阵,但您可以像这样使用 scipy.sparse
:
data = pd.Series([list('ABC'),list('DEF'),list('ABEF')])
from scipy.sparse import csr_matrix
cols, ind = np.unique(np.concatenate(data), return_inverse=True)
indptr = np.cumsum([0] + list(map(len, data)))
vals = np.ones_like(ind)
M = csr_matrix((vals, ind, indptr))
此稀疏矩阵现在包含与 pandas 解相同的数据,但未明确存储零。我们可以通过将稀疏矩阵转换为数据帧来确认这一点:
>>> pd.DataFrame(M.toarray(), columns=cols)
A B C D E F
0 1 1 1 0 0 0
1 0 0 0 1 1 1
2 1 1 0 0 1 1
根据您对此处数据的处理方式,采用稀疏形式可能有助于在不使用过多内存的情况下解决您的问题。
在之前的帖子中,对以下问题(Pandas: reshaping data)给出了精彩的回答。 目标是通过以下方式将包含列表的 pandas 系列重塑为 pandas 数据框:
In [9]: s = Series([list('ABC'),list('DEF'),list('ABEF')])
In [10]: s
Out[10]:
0 [A, B, C]
1 [D, E, F]
2 [A, B, E, F]
dtype: object
应该变成这样:
Out[11]:
A B C D E F
0 1 1 1 0 0 0
1 0 0 0 1 1 1
2 1 1 0 0 1 1
也就是说,创建一个数据框,其中系列列表中的每个元素都成为一列。对于系列中的每个元素,都会在数据框中创建一行。对于列表中的每个元素,将 1 分配给相应的数据框列(否则为 0)。我知道措辞可能很繁琐,但希望上面的例子很清楚。
用户 Jeff (https://whosebug.com/users/644898/jeff) 的精彩回应是编写了这行简单而强大的代码:
In [11]: s.apply(lambda x: Series(1,index=x)).fillna(0)
将 [10] 转换为 [11]。
这行代码对我来说非常有用,但是我 运行 遇到了一系列大约 50K 元素和所有列表中大约 100K 不同元素的内存问题。我的机器有16G内存。在求助于更大的机器之前,我想考虑一个更高效的实现上面的功能。
有谁知道如何重新实现上面的行:
In [11]: s.apply(lambda x: Series(1,index=x)).fillna(0)
在内存使用方面提高效率?
您可以尝试将数据帧分成多个块并边写边写入文件,如下所示:
chunksize = 10000
def f(df):
return f.apply(lambda x: Series(1,index=x)).fillna(0)
with open('out.csv','w') as f:
f.write(df.ix[[]].to_csv()) #write the header
for chunk in df.groupby(np.arange(len(df))//chunksize):
f.write(f(chunk).to_csv(header=None))
如果内存使用是问题,那么稀疏矩阵解决方案似乎会更好。 Pandas 并不真正支持稀疏矩阵,但您可以像这样使用 scipy.sparse
:
data = pd.Series([list('ABC'),list('DEF'),list('ABEF')])
from scipy.sparse import csr_matrix
cols, ind = np.unique(np.concatenate(data), return_inverse=True)
indptr = np.cumsum([0] + list(map(len, data)))
vals = np.ones_like(ind)
M = csr_matrix((vals, ind, indptr))
此稀疏矩阵现在包含与 pandas 解相同的数据,但未明确存储零。我们可以通过将稀疏矩阵转换为数据帧来确认这一点:
>>> pd.DataFrame(M.toarray(), columns=cols)
A B C D E F
0 1 1 1 0 0 0
1 0 0 0 1 1 1
2 1 1 0 0 1 1
根据您对此处数据的处理方式,采用稀疏形式可能有助于在不使用过多内存的情况下解决您的问题。