【问题标题】:Pandas crosstab on very large matrix?非常大的矩阵上的熊猫交叉表?
【发布时间】:2020-06-09 17:23:51
【问题描述】:

我有一个维度(4200 万行,6 列)的数据框,我需要对其进行交叉表计算,以获取数据集中每个人的特定事件的计数,这将导致一个非常大的稀疏矩阵,大小约为 1.5百万行乘以 36,000 列。当我使用 pandas crosstab (pd.crosstab) 函数尝试此操作时,我的系统内存不足。有没有办法分块做这个交叉表并加入生成的数据帧?需要明确的是,交叉表的每一行都将计算数据集中每个人发生的事件的次数(即每一行是一个人,每个列条目是该人参与特定事件的次数)。最终目标是使用 PCA/SVD 分解生成的人员事件矩阵。

【问题讨论】:

  • 你可以试试 dask 但是,考虑到矩阵会很稀疏,我宁愿做一个 groupby 事件,人数统计并尝试从那里排列数据。
  • 感谢您的建议,但如果我理解正确,我认为这不适用于我的应用程序。我需要尝试考虑这个人员事件矩阵(PCA 或 SVD),所以我需要保留人员级别的数据。
  • 这可能会有所帮助:stackoverflow.com/questions/44729727/…
  • 感谢您提供有用的链接!

标签: python pandas bigdata


【解决方案1】:

设置

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.Seriesunstack 以验证它是我们想要的。

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

【讨论】:

  • 有趣的建议。您正在使用一些我不熟悉的方法。为确保我理解,在您创建的 df 中,“源 1”列将具有该人的重复 id(每次发生事件时重复),而“源 2”将具有事件类型 id?
  • 是的!但是,如果您提出自己的一些示例数据,我很乐意重复该过程。另外,我也在努力包含一些稀疏解决方案
  • 聪明的解决方案,谢谢!有没有办法使用 scipy.sparse.csc_matrix 将你的两列 df 分解成一个稀疏矩阵,以便下一步我可以使用 sklearn 中的 TruncatedSVD() 之类的东西对 PCA/SVD 进行因式分解?
  • 谢谢!看起来很有希望。如果它对我有用,我会试一试并接受答案。
  • 我在尝试您的 scipy 稀疏矩阵解决方案时遇到错误。具体来说,这一行:“ij, tups = pd.factorize(list(zip(i, j)))”给了我“ValueError: Buffer has wrong number of dimensions (expected 1, got 2)”。两条 pd.factorize() 行似乎工作正常。有什么建议吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
  • 2021-04-09
  • 1970-01-01
  • 2011-03-11
  • 2021-01-12
  • 2018-04-02
  • 1970-01-01
相关资源
最近更新 更多