2015-06-27 92 views
11

有沒有辦法將pandas.SparseDataFrame轉換爲scipy.sparse.csr_matrix,而不會在內存中生成一個密集的矩陣?熊貓稀疏dataFrame稀疏矩陣,沒有在內存中生成一個密集的矩陣

scipy.sparse.csr_matrix(df.values) 

不起作用,因爲它會生成一個緻密的矩陣,投射到csr_matrix

提前致謝!有關實驗轉換

+0

運行此相反? http://stackoverflow.com/questions/17818783/populate-a-pandas-sparsedataframe-from-a-scipy-sparse-matrix – JohnE

回答

0

熊貓文檔會談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月)。

+0

這隻適用於'MultiIndex'-ed'SparseSeries',不適用於DataFrame。 –

+0

作爲@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())'是可以實現這一功能的單線程。也許你應該編輯你的答案,以明確這一點? –

+0

也許我們應該接近主題日期? – hpaulj

0

下面是一個按列填充稀疏矩陣的解決方案(假設您可以將至少一列填充到內存中)。

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() 
3

@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() 
6

熊貓0.20.0+:

由於大熊貓版本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() 
+0

如何使用'series.to_coo()'轉換每列,並使用'sparse.bmat()'將它們加入到一個矩陣中? – hpaulj

+0

@hpaulj這聽起來像一個明確的答案 - 你應該寫出來! –

+0

進一步挖掘我發現Multiindex映射與我想到的簡單列向量非常不同。它更像是「sklearn」人喜歡的特徵矩陣。 – hpaulj

-1

EDIT:這種方法實際上是具有在某個階段緻密的顯示,所以它並沒有解決的問題。

您應該能夠以下面的方式使用實驗.to_coo()方法在大熊貓[1]:

df, idx_rows, idx_cols = df.stack().to_sparse().to_coo() 
df = df.tocsr() 

這種方法,而不是取DataFrame(行/列)它需要與行的SeriesMultiIndex中的列(這就是爲什麼您需要.stack()方法)。此SeriesMultiIndex需要爲SparseSeries,即使您的輸入爲SparseDataFrame,.stack()也會返回常規Series。因此,在撥打.to_coo()之前,您需要使用.to_sparse()方法。

Series通過.stack()返回,即使它不是一個SparseSeries僅包含非空的元素,所以(當類型爲np.float至少有np.nan)不應該採取更多的內存比稀疏的版本。

  1. http://pandas.pydata.org/pandas-docs/stable/sparse.html#interaction-with-scipy-sparse
+0

這種方法似乎很遺憾地使用了大量的內存。 – eleanora

+0

你是對的@eleanora,不知道我以前如何測試過它,但它看起來像內部這個方法有一個密集的數組內部表示,所以這個問題沒有意義。對不起,錯誤的答案。 –

+0

現在看來這個工作。 'dataset = sparse.csr_matrix(df.to_coo())' – eleanora