Pandas кросс-таблица на очень большой матрице? - PullRequest
1 голос
/ 26 февраля 2020

У меня есть блок данных измерений (42 миллиона строк, 6 столбцов), для которого мне нужно сделать перекрестную таблицу, чтобы получить счетчик определенных c событий для каждого человека в наборе данных, что приведет к очень большой разреженной матрице размер ~ 1,5 миллиона строк по 36000 столбцов. Когда я пытаюсь сделать это с помощью функции pandas crosstab (pd.crosstab), в моей системе заканчивается память. Есть ли какой-нибудь способ сделать эту кросс-таблицу в блоках и соединить получившиеся кадры данных? Чтобы было ясно, каждая строка кросс-таблицы будет подсчитывать количество раз, когда событие происходило для каждого человека в наборе данных (т. Е. Каждая строка - это человек, каждая запись в столбце - это количество раз, когда этот человек участвовал в указанном c событие). Конечная цель состоит в том, чтобы проанализировать полученную матрицу человек-событие, используя PCA / SVD.

1 Ответ

2 голосов
/ 26 февраля 2020

Настройка

source_0 = [*'ABCDEFGHIJ']
source_1 = [*'abcdefghij']

np.random.seed([3, 1415])

df = pd.DataFrame({
    'source_0': np.random.choice(source_0, 100),
    'source_1': np.random.choice(source_1, 100),
})

df

   source_0 source_1
0         A        b
1         C        b
2         H        f
3         D        a
4         I        h
..      ...      ...
95        C        f
96        F        a
97        I        j
98        I        d
99        J        b

Используйте pd.factorize для получения целочисленной факторизации ... и уникальных значений

ij, tups = pd.factorize(list(zip(*map(df.get, df))))
result = dict(zip(tups, np.bincount(ij)))

Это уже компактная форма. Но вы можете преобразовать его в pandas.Series и unstack, чтобы убедиться, что это то, что нам нужно.

pd.Series(result).unstack(fill_value=0)

   a  b  c  d  e  f  g  h  i  j
A  2  1  0  0  0  1  0  2  1  1
B  0  1  0  0  0  1  0  1  0  1
C  0  3  1  3  0  2  0  0  0  0
D  3  0  0  2  0  0  1  3  0  2
E  3  0  0  1  0  1  2  5  0  0
F  4  0  2  1  1  1  1  1  1  0
G  0  2  1  0  0  2  3  0  3  1
H  1  3  2  0  2  1  1  1  0  2
I  2  2  1  1  2  0  1  2  0  2
J  0  1  1  0  1  1  0  1  0  1

Использование sparse

from scipy.sparse import csr_matrix

i, r = pd.factorize(df['source_0'])
j, c = pd.factorize(df['source_1'])
ij, tups = pd.factorize(list(zip(i, j)))

a = csr_matrix((np.bincount(ij), tuple(zip(*tups))))

b = pd.DataFrame.sparse.from_spmatrix(a, r, c).sort_index().sort_index(axis=1)

b

   a  b  c  d  e  f  g  h  i  j
A  2  1  0  0  0  1  0  2  1  1
B  0  1  0  0  0  1  0  1  0  1
C  0  3  1  3  0  2  0  0  0  0
D  3  0  0  2  0  0  1  3  0  2
E  3  0  0  1  0  1  2  5  0  0
F  4  0  2  1  1  1  1  1  1  0
G  0  2  1  0  0  2  3  0  3  1
H  1  3  2  0  2  1  1  1  0  2
I  2  2  1  1  2  0  1  2  0  2
J  0  1  1  0  1  1  0  1  0  1
...