stats.mannwhitneyu的奇怪结果表格

问题描述 投票:1回答:1

如标题中所述,从stats.mannwhitneyu估计scipy时,我遇到了一种奇怪的情况。

玩具数据和代码:

import numpy as np
import pandas as pd
from scipy import stats

# data 
np.random.seed(0)  

df = pd.DataFrame(np.random.randint(0,100,size=(100, 2)), columns=['col_1','col_2'])
df['group_l1'] = ['A']*50 + ['B']*50
df['group_l2'] = ['x']*25 + ['y']*25 +   ['x']*25 + ['y']*25

[如test部分中所示,当我使用group_l2时,我将被col_1分割的数据用作两个样本,以便为每个col_2组中的group_l1ttest_ind进行测试。作为测试:

# test

df[['col_1','col_2','group_l1','group_l2']].groupby('group_l1').\
apply(lambda x: stats.ttest_ind(x.groupby('group_l2')[['col_1','col_2']].get_group('x'),
                                x.groupby('group_l2')[['col_1','col_2']].get_group('y'))[1])

结果是:

group_l1
A     [0.7746267572903867, 0.9459142110158605]
B    [0.7016762873007549, 0.09047806237946462]

这就是我想要的,但是当我使用mannwhitneyu时,结果是:

df[['col_1','col_2','group_l1','group_l2']].groupby('group_l1').\
    apply(lambda x: stats.mannwhitneyu(x.groupby('group_l2')[['col_1','col_2']].get_group('x'),
                                    x.groupby('group_l2')[['col_1','col_2']].get_group('y'))[1])


group_l1
A    3.412244e-35
B    7.872898e-33

似乎只计算了一列,任何人都知道为什么会这样吗?

python scipy apply
1个回答
0
投票

发生这种情况的原因有两个,在ttest_ind()中为一个原因,在manwhitneyu()中为一个原因。

ttest_ind()中,签名的默认值为axis=0https://github.com/scipy/scipy/blob/41763e3ea532fc0e9305dde87a48ab3b4d14eac8/scipy/stats/stats.py#L5124

然后在文档字符串之后,该函数调用_chk2_asarray(a,b,axis)以确保参数a,b与数组相似。https://github.com/scipy/scipy/blob/41763e3ea532fc0e9305dde87a48ab3b4d14eac8/scipy/stats/stats.py#L5220现在_chk2_asarray()得到了axis=0的默认值,这意味着a,b都在这里通过np.asarray()传递:https://github.com/scipy/scipy/blob/41763e3ea532fc0e9305dde87a48ab3b4d14eac8/scipy/stats/stats.py#L235-L237所以一切都很好。但是,如果您将axis替换为ttest_ind()中的默认axis=None参数,则您将碰到另一个代码路径_chk2_asarray(),您将遍历np.ravel(a)和类似的b参数。这将“拆栈”您的阵列并破坏分组。例如,使用帖子中提供的数据:

>>> df[['col_1','col_2','group_l1','group_l2']].groupby('group_l1').\
... apply(lambda x: stats.ttest_ind(x.groupby('group_l2')[['col_1','col_2']].get_group('x'),
...                                 x.groupby('group_l2')[['col_1','col_2']].get_group('y'), axis=None)[1])
group_l1
A    0.138643
B    0.942884
dtype: float64

现在,在mannwhitneyu()函数中,必须对数据进行排名以计算测试统计量。 scipy排名方法适用于单个数组,使用scipy.stats中的一个称为rankdata()的数组,这是到源的链接:

https://github.com/scipy/scipy/blob/41763e3ea532fc0e9305dde87a48ab3b4d14eac8/scipy/stats/stats.py#L7307函数内部的数组a立即在此处ravel() -ed:https://github.com/scipy/scipy/blob/41763e3ea532fc0e9305dde87a48ab3b4d14eac8/scipy/stats/stats.py#L7363这会破坏熊猫数据框参数中的结构。

解决方法是手动分离两个数据框并在每个数据框上运行,例如一个具有col_1的数据帧,另一个具有col_2的数据帧。当然,除非您希望所有内容都一起作为结果在两个数组中聚合。

我不确定是否可以通过更改代码来适应您想做的简单工作。您可以随时向scipy-dev电子邮件列表发送查询以提出更改,但是对我来说这尚不明显。您需要在每一列中进行排名,因此这将需要不同的(或自定义)排名功能。

希望这可以帮助您了解正在发生的事情,这里发生的事情并不明显,这让我有所挖掘。

© www.soinside.com 2019 - 2024. All rights reserved.