Преобразование списка счетчиков в разреженные панды DataFrame - PullRequest
0 голосов
/ 30 октября 2019

У меня проблемы с созданием pandas DataFrame с разреженным dtype. Мои данные представляют собой набор векторов объектов, хранящихся в виде диктов или счетчиков. При таких разреженных данных, как представление текста в виде пакета слов, часто неуместно и невозможно хранить данные в виде плотного документа с кратной матрицей, и это необходимо для поддержания разреженности структуры данных.

ДляНапример, скажем, что ввод:

docs = [{'hello': 1}, {'world': 1, '!': 2}]

Вывод должен быть эквивалентен:

import pandas as pd
out = pd.DataFrame(docs).astype(pd.SparseDtype(float))

без создания плотных массивов по пути. (Мы можем проверить out.dtypes и out.sparse.density.)

Попытка 1:

out = pd.DataFrame(dtype=pd.SparseDtype(float))
out.loc[0, 'hello'] = 1
out.loc[1, 'world'] = 1
out.loc[1, '!'] = 2

Но это создает плотную структуру данных.

Попытка 2:

out = pd.DataFrame({"hello": pd.SparseArray([]),
                    "world": pd.SparseArray([]),
                    "!": pd.SparseArray([])})
out.loc[0, 'hello'] = 1

Но это поднимает TypeError: SparseArray does not support item assignment via setitem.

Решение, которое я в итоге нашел ниже, не работало в более ранних версиях Pandas, где я его пробовал.

1 Ответ

0 голосов
/ 30 октября 2019

Это похоже на работу в Пандах 0.25.1:

out = pd.DataFrame([[0, 'hello', 1], [1, 'world', 1], [1, '!', 2]],
                   columns=['docid', 'word', 'n'])
out = out.set_index(['docid', 'word'])['n'].astype(pd.SparseDtype(float))
out = out.unstack()

Или более обобщенно:

def dicts_to_sparse_dataframe(docs):
    rows = ((i, k, v)
            for i, doc in enumerate(docs)
            for k, v in doc.items())
    out = pd.DataFrame(rows, columns=['docid', 'word', 'n'])
    out = out.set_index(['docid', 'word'])['n'].astype(pd.SparseDtype(float))
    out = out.unstack()
    return out

Тогда:

>>> docs = [{'hello': 1}, {'world': 1, '!': 2}]
>>> df = dicts_to_sparse_dataframe(docs)
>>> df.sparse.density
0.5

Я надеюсьэто не создает плотную структуру в памяти на этом пути ...

...