J'ai un cadre de données de dimensions (42 millions de lignes, 6 colonnes) sur lequel je dois effectuer un tableau croisé pour obtenir le nombre d'événements spécifiques pour chaque personne de l'ensemble de données, ce qui donnera une très grande matrice éparse de taille ~1,5 million de lignes par 36 000 colonnes. Lorsque j'essaie de le faire avec la fonction pandas crosstab (pd.crosstab), la mémoire de mon système est saturée. Existe-t-il un moyen d'effectuer ce tableau croisé par morceaux et de joindre les cadres de données résultants ? Pour être clair, chaque ligne du tableau croisé comptera le nombre de fois qu'un événement s'est produit pour chaque personne dans l'ensemble de données (c'est-à-dire que chaque ligne est une personne, chaque entrée de colonne est le nombre de fois que cette personne a participé à un événement spécifique). L'objectif final est de factoriser la matrice personne-événement résultante en utilisant PCA/SVD.
Réponse
Trop de publicités?Configuration
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
Utilisez pd.factorize
pour obtenir une factorisation entière... et des valeurs uniques
ij, tups = pd.factorize(list(zip(*map(df.get, df))))
result = dict(zip(tups, np.bincount(ij)))
Il s'agit déjà d'une forme compacte. Mais vous pouvez la convertir en un pandas.Series
y unstack
pour vérifier que c'est bien ce que nous voulons.
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
Utilisation de 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