【发布时间】:2021-06-07 05:55:41
【问题描述】:
问题
我在 Python 3.7.7 上使用 Pandas。我想计算由另一个变量的值y 分组的变量x 的分类值之间的互信息。我的数据如下表所示:
+-----+-----+
| x | y |
+-----+-----+
| x_1 | y_1 |
| x_2 | y_1 |
| x_3 | y_1 |
| x_1 | y_2 |
| x_2 | y_2 |
| x_4 | y_3 |
| x_6 | y_3 |
| x_9 | y_3 |
| x_1 | y_4 |
| ... | ... |
+-----+-----+
我想要一个数据结构(pandas MultiIndex 系列/数据框或 numpy 矩阵或任何合适的),它存储 (x_i, x_j) 对的共现数y_k 值。事实上,这会很棒,例如,可以轻松计算 PMI:
+-----+-----+--------+-------+
| x_i | x_j | cooc | pmi |
+-----+-----+--------+-------+
| x_1 | x_2 | | |
| x_1 | x_3 | | |
| x_1 | x_4 | | |
| x_1 | x_5 | | |
| ... | ... | ... | ... |
+-----+-----+--------+-------+
有没有合适的内存高效方式?
旁注:我正在使用相当大的数据(40k 不同的 x 值和 8k 不同的 y 值,总共 300k (x,y) 条目,所以内存友好和优化的方法会很棒(可能依赖第三方库作为Dask)
更新
未优化的解决方案
我想出了一个使用pd.crosstab 的解决方案。我在这里提供一个小例子:
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randint(0,100,size=(100, 2)), columns=list('xy'))
"""
df:
+-----+-----+
| x | y |
+-----+-----+
| 4 | 99 |
| 1 | 39 |
| 39 | 56 |
| .. | .. |
| 59 | 20 |
| 82 | 57 |
+-----+-----+
100 rows × 2 columns
"""
# Compute cross tabulation:
crosstab = pd.crosstab(df["x"], df["y"])
"""
crosstab:
+------+-----+-----+-----+-----+
| y | 0 | 2 | 3 | ... |
| x +-----+-----+-----+-----+
| 1 | 0 | 0 | 0 | ... |
| 2 | 0 | 0 | 0 | ... |
| ... | ... | ... | ... | ... |
+------+-----+-----+-----+-----+
62 rows × 69 columns
"""
# Initialize a pandas MultiIndex Series storing PMI values
import itertools
x_pairs = list(itertools.combinations(crosstab.index, 2))
pmi = pd.Series(0, index = pd.MultiIndex.from_tuples(x_pairs))
"""
pmi:
+-------------+-----+
| index | val |
+------+------| |
| x_i | x_j | |
+------+------+-----+
| 1 | 2 | 0 |
| | 4 | 0 |
| ... | ... | ... |
| 95 | 98 | 0 |
| | 99 | 0 |
| 96 | 98 | 0 |
+------+------+-----+
Length: 1891, dtype: int64
"""
然后,我用来填充系列的循环结构如下:
for x1, x2 in x_pairs:
pmi.loc[x1, x2] = crosstab.loc[[x1, x2]].min().sum() / (crosstab.loc[x1].sum() * crosstab.loc[x2].sum())
这不是一个可选的解决方案,即使在小型用例中也表现不佳。
【问题讨论】:
-
我遇到了同样的问题,但最后通过过滤掉频率最低的数据来创建同现矩阵。
-
这将是减少条目的一个很好的解决方案,但它并不能解决大数据规模问题。事实上,在我的情况下,我的同现频率非常低,根据它们的频率进行过滤并不是最好的解决方案。
-
假设只有一些
x组合会被观察到是否公平? (使用稀疏矩阵表示) -
没错,@SultanOrazbayev,从 40k
xdistinct 值和 8kydistinct 值,初始数据帧中的 300k 行不涵盖x值的全部 1.6M 组合 -
@SultanOrazbayev 我终于设法使用稀疏矩阵做到了,谢谢!
标签: python pandas data-science dask data-analysis