有沒有辦法將pandas.SparseDataFrame
轉換爲scipy.sparse.csr_matrix
,而不會在內存中生成一個密集的矩陣?熊貓稀疏dataFrame稀疏矩陣,沒有在內存中生成一個密集的矩陣
scipy.sparse.csr_matrix(df.values)
不起作用,因爲它會生成一個緻密的矩陣,投射到csr_matrix
。
提前致謝!有關實驗轉換
有沒有辦法將pandas.SparseDataFrame
轉換爲scipy.sparse.csr_matrix
,而不會在內存中生成一個密集的矩陣?熊貓稀疏dataFrame稀疏矩陣,沒有在內存中生成一個密集的矩陣
scipy.sparse.csr_matrix(df.values)
不起作用,因爲它會生成一個緻密的矩陣,投射到csr_matrix
。
提前致謝!有關實驗轉換
熊貓文檔會談SciPy的稀疏,SparseSeries.to_coo:
http://pandas-docs.github.io/pandas-docs-travis/sparse.html#interaction-with-scipy-sparse
================
編輯 - 這是多索引而不是數據幀的特殊功能。請參閱其他答案。請注意日期的差異。
============
作爲0.20.0,有一個sdf.to_coo()
和多指標ss.to_coo()
。由於稀疏矩陣本質上是2D的,因此需要(有效)1d數據集的多索引是有意義的。而數據框可以表示一個表或二維數組。
當我第一次回答這個問題時,這個稀疏的數據框/系列功能是實驗性的(2015年6月)。
這隻適用於'MultiIndex'-ed'SparseSeries',不適用於DataFrame。 –
作爲@eleanora提到,[現在確實有效](http://pandas-docs.github.io/pandas-docs-travis/generated/pandas.SparseDataFrame.to_coo.html#pandas.SparseDataFrame.to_coo)(as版本0.20.0,2017年5月5日發佈)。 'sparse.csr_matrix(df.to_coo())'是可以實現這一功能的單線程。也許你應該編輯你的答案,以明確這一點? –
也許我們應該接近主題日期? – hpaulj
下面是一個按列填充稀疏矩陣的解決方案(假設您可以將至少一列填充到內存中)。
import pandas as pd
import numpy as np
from scipy.sparse import lil_matrix
def sparse_df_to_array(df):
""" Convert sparse dataframe to sparse array csr_matrix used by
scikit learn. """
arr = lil_matrix(df.shape, dtype=np.float32)
for i, col in enumerate(df.columns):
ix = df[col] != 0
arr[np.where(ix), i] = df.ix[ix, col]
return arr.tocsr()
@Marigold的答案可以做到這一點,但由於訪問每列中的所有元素(包括零),它的速度很慢。在此基礎上,我編寫了以下快速n'髒代碼,它在密度約爲1%的1000x1000矩陣上運行速度提高了50倍。我的代碼也適當地處理密集列。
def sparse_df_to_array(df):
num_rows = df.shape[0]
data = []
row = []
col = []
for i, col_name in enumerate(df.columns):
if isinstance(df[col_name], pd.SparseSeries):
column_index = df[col_name].sp_index
if isinstance(column_index, BlockIndex):
column_index = column_index.to_int_index()
ix = column_index.indices
data.append(df[col_name].sp_values)
row.append(ix)
col.append(len(df[col_name].sp_values) * [i])
else:
data.append(df[col_name].values)
row.append(np.array(range(0, num_rows)))
col.append(np.array(num_rows * [i]))
data_f = np.concatenate(data)
row_f = np.concatenate(row)
col_f = np.concatenate(col)
arr = coo_matrix((data_f, (row_f, col_f)), df.shape, dtype=np.float64)
return arr.tocsr()
由於大熊貓版本0.20.0,2017年5月5日發佈的,還有一個班輪此:
from scipy import sparse
def sparse_df_to_csr(df):
return sparse.csr_matrix(df.to_coo())
這將使用新to_coo()
method。
大廈維克多五月的答案,這裏有一個稍快的實現,但它僅適用,如果整個SparseDataFrame
是稀疏的所有BlockIndex
(注:若曾get_dummies
創建的,這將是案件)。
編輯:我修改了這個,所以它可以使用非零填充值。 CSR沒有本地非零填充值,因此您必須在外部記錄它。
import numpy as np
import pandas as pd
from scipy import sparse
def sparse_BlockIndex_df_to_csr(df):
columns=df.columns
zipped_data = zip(*[(df[col].sp_values - df[col].fill_value,
df[col].sp_index.to_int_index().indices)
for col in columns])
data, rows=map(list, zipped_data)
cols=[np.ones_like(a)*i for (i,a) in enumerate(data)]
data_f = np.concatenate(data)
rows_f = np.concatenate(rows)
cols_f = np.concatenate(cols)
arr = sparse.coo_matrix((data_f, (rows_f, cols_f)),
df.shape, dtype=np.float64)
return arr.tocsr()
EDIT:這種方法實際上是具有在某個階段緻密的顯示,所以它並沒有解決的問題。
您應該能夠以下面的方式使用實驗.to_coo()
方法在大熊貓[1]:
df, idx_rows, idx_cols = df.stack().to_sparse().to_coo()
df = df.tocsr()
這種方法,而不是取DataFrame
(行/列)它需要與行的Series
和MultiIndex
中的列(這就是爲什麼您需要.stack()
方法)。此Series
與MultiIndex
需要爲SparseSeries
,即使您的輸入爲SparseDataFrame
,.stack()
也會返回常規Series
。因此,在撥打.to_coo()
之前,您需要使用.to_sparse()
方法。
的Series
通過.stack()
返回,即使它不是一個SparseSeries
僅包含非空的元素,所以(當類型爲np.float
至少有np.nan
)不應該採取更多的內存比稀疏的版本。
運行此相反? http://stackoverflow.com/questions/17818783/populate-a-pandas-sparsedataframe-from-a-scipy-sparse-matrix – JohnE