【发布时间】:2018-02-25 20:45:04
【问题描述】:
我的数据是一组 n 观察到的对及其频率,即每对 (xi, yi)里面对应一些ki,次数(xi,yi) 被观察到。理想情况下,我想为这些对的所有副本的集合计算 Kendall 的 tau 和 Spearman 的 rho,其中包括 k1 + k2 + ... + kn 对。问题是k1 + k2 + ... + kn,观察的总数, 是巨大的,这样的数据结构不适合内存。
当然,我考虑分配第i对的频率,ki/(k1 + k2 + ... + kn),作为其权重,并计算加权集的等级相关性——但我找不到任何工具.在我遇到的各种加权等级相关性(例如,scipy.stats.weightedtau)中,权重代表等级而不是对的重要性,这与我的事业无关。 Pearson 的 r 似乎正好有我需要的加权选项,但它不符合我的目的,因为 x 和 y 没有线性相关。我想知道我是否遗漏了一些关于加权数据点的广义相关性的概念。
到目前为止我唯一的想法是缩小 k1, k2, ..., kn sub> 乘以某个公因子 c,因此第 i 对的缩放副本数为 [ki/c] (这里 [.] 是舍入运算符,因为我们需要每对有整数个副本)。通过选择 c 使得 [k1/c] + [k2/c] + ... + [kn/c] 对可以放入内存,然后我们可以计算结果集的相关系数 tau 和 rho。但是,ki 和 kj 可以相差多个数量级,因此 c i> 对于某些 ki 可能非常大,因此四舍五入 ki/c 会导致信息丢失。
UPD:可以在具有指定频率权重的数据集上计算 Spearman 的 rho 和 p 值,如下所示:
def frequency_pearsonr(data, frequencies):
"""
Calculates Pearson's r between columns (variables), given the
frequencies of the rows (observations).
:param data: 2-D array with data
:param frequencies: 1-D array with frequencies
:return: 2-D array with pairwise correlations,
2-D array with pairwise p-values
"""
df = frequencies.sum() - 2
Sigma = np.cov(data.T, fweights=frequencies)
sigma_diag = Sigma.diagonal()
Sigma_diag_pairwise_products = np.multiply.outer(sigma_diag, sigma_diag)
# Calculate matrix with pairwise correlations.
R = Sigma / np.sqrt(Sigma_diag_pairwise_products)
# Calculate matrix with pairwise t-statistics. Main diagonal should
# get 1 / 0 = inf.
with np.errstate(divide='ignore'):
T = R / np.sqrt((1 - R * R) / df)
# Calculate matrix with pairwise p-values.
P = 2 * stats.t.sf(np.abs(T), df)
return R, P
def frequency_rank(data, frequencies):
"""
Ranks 1-D data array, given the frequency of each value. Same
values get same "averaged" ranks. Array with ranks is shaped to
match the input data array.
:param data: 1-D array with data
:param frequencies: 1-D array with frequencies
:return: 1-D array with ranks
"""
s = 0
ranks = np.empty_like(data)
# Compute rank for each unique value.
for value in sorted(set(data)):
index_grid = np.ix_(data == value)
# Find total frequency of the value.
frequency = frequencies[index_grid].sum()
ranks[index_grid] = s + 0.5 * (frequency + 1)
s += frequency
return ranks
def frequency_spearmanrho(data, frequencies):
"""
Calculates Spearman's rho between columns (variables), given the
frequencies of the rows (observations).
:param data: 2-D array with data
:param frequencies: 1-D array with frequencies
:return: 2-D array with pairwise correlations,
2-D array with pairwise p-values
"""
# Rank the columns.
ranks = np.empty_like(data)
for i, data_column in enumerate(data.T):
ranks[:, i] = frequency_rank(data_column, frequencies)
# Compute Pearson's r correlation and p-values on the ranks.
return frequency_pearsonr(ranks, frequencies)
# Columns are variables and rows are observations, whose frequencies
# are specified.
data_col1 = np.array([1, 0, 1, 0, 1])
data_col2 = np.array([.67, .25, .75, .2, .6])
data_col3 = np.array([.1, .3, .8, .3, .2])
data = np.array([data_col1, data_col2, data_col3]).T
frequencies = np.array([2, 4, 1, 3, 2])
# Same data, but with observations (rows) actually repeated instead of
# their frequencies being specified.
expanded_data_col1 = np.array([1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1])
expanded_data_col2 = np.array([.67, .67, .25, .25, .25, .25, .75, .2, .2, .2, .6, .6])
expanded_data_col3 = np.array([.1, .1, .3, .3, .3, .3, .8, .3, .3, .3, .2, .2])
expanded_data = np.array([expanded_data_col1, expanded_data_col2, expanded_data_col3]).T
# Compute Spearman's rho for data in both formats, and compare.
frequency_Rho, frequency_P = frequency_spearmanrho(data, frequencies)
Rho, P = stats.spearmanr(expanded_data)
print(frequency_Rho - Rho)
print(frequency_P - P)
上面的特定示例表明两种方法产生相同的相关性和相同的 p 值:
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 1.11022302e-16 0.00000000e+00 -5.55111512e-17]
[ 0.00000000e+00 -5.55111512e-17 0.00000000e+00]]
[[ 0.00000000e+00 -1.35525272e-19 4.16333634e-17]
[ -9.21571847e-19 0.00000000e+00 -5.55111512e-17]
[ 4.16333634e-17 -5.55111512e-17 0.00000000e+00]]
【问题讨论】:
-
要计算加权 Spearman 等级相关系数,您可以简单地预先排列您的 x 和 y 值,然后将它们推入
pearsonr(连同您的权重)以获得加权 Spearman 的 rho . -
不确定以下方法的统计有效性,但从技术角度来看,您可以简单地将(预先计算的)字典映射等级封装到函数中的归一化频率并将其作为 @ 987654325@到
weightedtau。 -
让我直接回答你的问题,k1 + k2 + ... + kn 对观测值太大而无法放入 RAM。你能在随机样本上计算秩相关,增加样本量,重复这个过程,直到估计的秩相关低于某个阈值水平吗?
-
@Paul,您能否澄清一下您所说的“pre-rank”是什么意思?我认为您的第二个建议是有道理的,如果排名有任何不同(例如指数)并且交换权重是权重的乘积而不是总和(“additive = False”)。确实,如果 (x1, y1) 发生了 5 次, (x2, y2) 发生了 10 次,那么它们的交换权重∝ 50,也就是这次交换的次数,(x1, y1) (x2 , y2),如果在具有 5 个 (x1, y1) 实例和 10 个 (x2, y2) 实例的“扩展”数据集上计算常规 tau 相关性,将会发生。我会对此进行测试并报告。
-
@CTZhu 是的,你没看错,k1 + k2 + ... + kn 观察无法放入内存。事实上,它可能比内存容量大很多数量级。我不确定你在说什么阈值,因为我没有任何关于相关性应该是什么的先验。如果对于每个样本量,相关性都显着不同(这可能是因为任何内存可行的样本量都几乎没有足够的代表性),那么我们该怎么办?
标签: python algorithm scipy statistics correlation