web-dev-qa-db-ja.com

PandasスパースdataFrameからスパース行列へ、メモリ内に密行列を生成せずに

メモリ内に密行列を生成せずに、pandas.SparseDataFrameからscipy.sparse.csr_matrixに変換する方法はありますか?

scipy.sparse.csr_matrix(df.values)

csr_matrixにキャストされる密行列を生成するため機能しません。

前もって感謝します!

14
Jake0x32

Pandasのドキュメントでは、scipysparseへの実験的な変換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()があります。スパース行列は本質的に2次元であるため、(事実上)1次元データシリーズに多重指数を要求することは理にかなっています。データフレームはテーブルまたは2D配列を表すことができますが。

この質問に最初に回答したとき、このスパースデータフレーム/シリーズ機能は実験的なものでした(2015年6月)。

0
hpaulj

パンダ0.20.0+:

2017年5月5日にリリースされたpandasバージョン0.20.0)の時点で、これにはワンライナーがあります。

_from scipy import sparse


def sparse_df_to_csr(df):
    return sparse.csr_matrix(df.to_coo())
_

これは、新しい to_coo()メソッド を使用します。

以前のバージョン:

Victor Mayの回答に基づいて、これは少し高速な実装ですが、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()
_
14
T.C. Proctor

@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()
3
Victor May

Pandasバージョン0.25SparseSeriesおよびSparseDataFrameは非推奨になりました。DataFramesは、スパースデータを含む列に対して スパースDtypes をサポートするようになりました。スパースメソッドsparseアクセサーを介して利用できるため、変換ワンライナーは次のようになります。

sparse_matrix = scipy.sparse.csr_matrix(df.sparse.to_coo())
2
Claygirl

これは、スパース行列を列ごとに埋めるソリューションです(少なくとも1つの列をメモリに収めることができると想定しています)。

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()
0
Marigold

[〜#〜] edit [〜#〜]:このメソッドは実際にはある段階で密な表現をしているので、問題を解決しません。

pandas [1]で実験的な.to_coo()メソッドを次のように使用できるはずです。

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

このメソッドは、DataFrame(行/列)を取得する代わりに、Seriesに行と列を含むMultiIndexを取得します(これが.stack() 方法)。このSeriesMultiIndexSparseSeriesである必要があり、入力がSparseDataFrameであっても、.stack()は通常の値を返します。 Series。したがって、.to_sparse()を呼び出す前に、.to_coo()メソッドを使用する必要があります。

.stack()によって返されるSeriesは、SparseSeriesでなくても、nullでない要素のみを含むため、スパースバージョンよりも多くのメモリを消費することはありません(タイプが_np.nan_の場合、少なくとも_np.float_で。

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