Преобразование pandas одного столбца в Scipy Sparse Matrix - PullRequest
0 голосов
/ 05 августа 2020

У меня есть кадр данных pandas вроде этого:

     a                           other-columns
   0.3 0.2 0.0 0.0 0.0...        ....

Я хочу преобразовать столбец a в разреженную матрицу CSR SciPy. a - это распределение вероятностей. Я хотел бы преобразовать без расширения a на несколько столбцов.

Это наивное решение с расширением a на несколько столбцов:

  df = df.join(df['a'].str.split(expand = True).add_prefix('a')).drop(['a'], axis = 1)
  df_matrix = scipy.sparse.csr_matrix(df.values)

Но я не хочу расширяться на несколько столбцов, так как это увеличивает память. Можно ли сделать это, сохранив a только в 1 столбце?

EDIT (минимальный воспроизводимый пример):

 import pandas as pd
 from scipy.sparse import csr_matrix
 d = {'a': ['0.05 0.0', '0.2 0.0']}
 df = pd.DataFrame(data=d)
 df = df.join(df['a'].str.split(expand = True).add_prefix('a')).drop(['a'], axis = 1)
 df = df.astype(float)
 df_matrix = scipy.sparse.csr_matrix(df.values)
 df_matrix

Вывод:

 <2x2 sparse matrix of type '<class 'numpy.float64'>'
with 2 stored elements in Compressed Sparse Row format>

I хотите достичь вышеуказанного, но без разделения на несколько столбцов. Кроме того, в моем реальном файле у меня есть 36 столбцов строки (разделенных пробелом) и миллионы строк. Уверен, что во всех строках будет 36 пробелов.

Ответы [ 2 ]

1 голос
/ 06 августа 2020

Кроме того, в моем реальном файле у меня есть 36 столбцов строки длины (разделенных пробелом) и миллионы строк. Уверен, что все строки будут содержать 36 пробелов.

Преобразование большого CSV в разреженную матрицу для использования в sklearn

Я не могу переоценить, сколько вам нужно не делайте того, что следует за этим предложением.

import pandas as pd
import numpy as np
from scipy import sparse

df = pd.DataFrame({'a': ['0.05 0.0', '0.2 0.0'] * 100000})
chunksize = 10000

sparse_coo = []
for i in range(int(np.ceil(df.shape[0]/chunksize))):
    chunk = df.iloc[i * chunksize:min(i * chunksize +chunksize, df.shape[0]), :]
    sparse_coo.append(sparse.coo_matrix(chunk['a'].apply(lambda x: [float(y) for y in x.split()]).tolist()))

sparse_coo = sparse.vstack(sparse_coo)
1 голос
/ 06 августа 2020

Вы можете получить плотный массив из столбца без расширения:

In [179]: df = pd.DataFrame(data=d)                                                                  

например,

In [180]: np.array(df['a'].str.split().tolist(),float)                                               
Out[180]: 
array([[0.05, 0.  ],
       [0.2 , 0.  ]])

Но я сомневаюсь, что это сэкономит много памяти (хотя у меня есть только грубое понимание использования памяти DataFrame.

Вы можете преобразовать каждую строку в разреженную матрицу:

In [190]: def foo(astr): 
     ...:     alist = astr.split() 
     ...:     arr = np.array(alist, float) 
     ...:     return sparse.coo_matrix(arr) 
                                                                                               
In [191]: alist = [foo(row) for row in df['a']]                                                      
In [192]: alist                                                                                      
Out[192]: 
[<1x2 sparse matrix of type '<class 'numpy.float64'>'
    with 1 stored elements in COOrdinate format>,
 <1x2 sparse matrix of type '<class 'numpy.float64'>'
    with 1 stored elements in COOrdinate format>]
In [193]: sparse.vstack(alist)                                                                       
Out[193]: 
<2x2 sparse matrix of type '<class 'numpy.float64'>'
    with 2 stored elements in COOrdinate format>

Я пытался сделать coo прямо из alist, но при этом не обрезаются нули. Преобразование такое же, но если оно достаточно разреженное (5% или меньше), оно может значительно сэкономить память (если не время).

sparse.vstack объединяет data,rows,cols значений из компонентных матриц для определения новой coo матрицы. Это самый простой способ комбинировать разреженные матрицы, если не самый быстрый.

Похоже, я мог бы использовать и apply

In [205]: df['a'].apply(foo)                                                                         
Out[205]: 
0      (0, 0)\t0.05
1       (0, 0)\t0.2
Name: a, dtype: object
In [206]: df['a'].apply(foo).values                                                                  
Out[206]: 
array([<1x2 sparse matrix of type '<class 'numpy.float64'>'
    with 1 stored elements in COOrdinate format>,
       <1x2 sparse matrix of type '<class 'numpy.float64'>'
    with 1 stored elements in COOrdinate format>], dtype=object)
In [207]: sparse.vstack(df['a'].apply(foo))                                                          
Out[207]: 
<2x2 sparse matrix of type '<class 'numpy.float64'>'
    with 2 stored elements in COOrdinate format>
...