将T-Test应用于Dataframe中的每个列

时间:2017-02-03 02:43:42

标签: python pandas statsmodels

我有一个数据框(我称之为PeerGroup),它有大约20个列,每个列有20个不同基金的月度回报,可追溯到大约十年。我试图确定过去三年的平均回报是否与整体往绩记录的平均值有统计差异。

目前,使用pandas,我可以像这样一次测试一列:

<script>
var reg = new RegExp("^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$");

    $('#button1').on('click', function() {
      var walletCheck = $('#wallet').val();
      if (reg.test(walletCheck)) {
        $('#button1').on('click', function() {

          var coinAmount = $('#bitcoin').val(),
            coinContent = 'BTC amount requested: ' + coinAmount,
            dollarAmount = $('#cad').val(),
            dollarContent = 'Market: $' + dollarAmount;
          feeAmount = dollarAmount * 0.08;
          feeContent = 'Fee: $' + feeAmount.toFixed(2);
          totalAmount = dollarAmount * 1.08;
          totalContent = 'Total: $' + totalAmount.toFixed(2);

          $('#btc-amount').html(coinContent);
          $('#cad-quote').html(dollarContent);
          $('#cad-fee').html(feeContent);
          $('#cad-total').html(totalContent);
          $("#step1").hide();
          $("#step2").show();
          $("#slogan").hide();
        });
      } else {
        alert("Invalid Bitcoin address, please make sure you've entered a valid address!");
      }
    });
  </script>

但是,如果可能的话,我想一次性对数据框中的每一列进行测试。我最好的想法是做这样的事情,但它变成了一个IndexError。有什么想法吗?

import pandas as pd
import statsmodels as st
PeerGroup = pd.read_excel['File\Path.xlsx']
df['Fund1'] = st.ttest_ind(PeerGroup['Column1'], PeerGroup['Column1'].tail(36), equal_var='False')

2 个答案:

答案 0 :(得分:1)

您在此处使用的pandas.DataFrame.apply方法将数据集的每个列作为单个lambda投放到Series函数中,但您的lambda已写入好像你正在获得一个列名。

为了说明,这是一个简单的例子:

>>> df = pd.DataFrame({'a': [1,2,3], 'b': [4,5,6]})

如果我们用print替换方法体,看看传递给函数的内容:

>>> df.apply(lambda x: print(x))
<<< 0    1
    1    2
    2    3
    Name: a, dtype: int64
    0    4
    1    5
    2    6
    Name: b, dtype: int64

您的方法调用无效,因为您正在使用一堆DataFrame个对象为Series建立索引,每个对象都是数据集的一列,pandas不会我不知道该怎么做:

>>> df.apply(lambda x: df[x])
<<< [...]
<<< IndexError

(作为一个小的一点,你可以索引一个DataFrame的{​​{1}}正确的“形状”;在这个玩具示例中尝试例如Series

由于已经您感兴趣的列,因此解决方案是简化。这应该有效:

df[pd.Series(['a'])]

答案 1 :(得分:0)

Statsmodels ttest_ind正在以矢量化方式计算t检验。

例如

>>> np.random.seed(123987)
>>> x = np.random.randn(50,5)
>>> import statsmodels.api as sm
>>> sm.stats.ttest_ind(x[:30], x[30:])
    (array([-0.95151202,  0.34686484, -1.85364701, -0.46793673,  0.06192139]), 
     array([ 0.34611141,  0.73020901,  0.06994078,  0.64194762,  0.95088256]), 48.0)

并使用显式循环检查

>>> np.array([sm.stats.ttest_ind(xi[:30], xi[30:])[:2] for xi in x.T]).T
array([[-0.95151202,  0.34686484, -1.85364701, -0.46793673,  0.06192139],
       [ 0.34611141,  0.73020901,  0.06994078,  0.64194762,  0.95088256]])

同样适用于pandas DataFrame。

注意,如果在t检验中比较的两个系列重叠,则两个样本不是独立的。最好测试系列第一部分的平均值是否与系列第二部分的平均值相同。
这仍然假设观察结果大致是连续不相关的。

修改
看起来导入的函数是指scipy.stats而不是statsmodels,它使用不同的关键字作为方差假设。 两者都以类似的方式工作(输出重新格式化以对齐数字)

>>> sm.stats.ttest_ind(x[:30], x[30:], usevar='unequal')
    (array([-0.91734136,  0.36226976, -1.91402235, -0.45593946,  0.06075814]), 
     array([ 0.36512018,  0.71880355,  0.06199039,  0.6510849 ,  0.95186872]), 
     array([ 35.6978717 ,  46.16729003,  44.9965459 ,  37.18892135,  38.18591126]))

>>> from scipy import stats
>>> stats.ttest_ind(x[:30], x[30:], equal_var=False)
Ttest_indResult(
statistic=array([-0.91734136,  0.36226976, -1.91402235, -0.45593946,  0.06075814]), 
   pvalue=array([ 0.36512018,  0.71880355,  0.06199039,  0.6510849 ,  0.95186872]))