4

假设我有一个带有二进制分组变量和一个因子的数据框。这种分组变量的一个示例可以指定分配给实验的处理和控制条件。在下面,b是分组变量,而a是任意因子变量:

a <- c("a","a","a","b","b")
b <- c(0,0,1,0,1)
df <- data.frame(a,b)

我想完成两个样本的 t 检验来评估以下内容:

  • 对于a 的每个水平,在b中指定的组之间采用该水平的平均倾向是否存在差异。

我使用dummies包为因子的每个级别创建单独的虚拟变量,然后手动对结果变量执行 t 检验:

library(dummies)
new <- dummy.data.frame(df, names = "a")
t.test(new$aa, new$b)
t.test(new$ab, new$b)

我正在寻求以下帮助:

  1. 有没有办法在不通过 dummy.data.frame() 创建大量虚拟变量的情况下执行此操作?
  2. 如果在不创建大量假人的情况下没有更快的方法来做到这一点,是否有更快的方法来完成跨多个列的 t 检验?

笔记

这类似于但不同于R - How to perform the same operation on multiple variables并且几乎与此问题Apply t-test on many columns in a dataframe split by factor但该问题的解决方案不再有效。

4

2 回答 2

2

这是一个基本R解决方案,实现了比例相等的 chi-squired 测试,我相信它更有可能回答您对数据提出的任何问题(请参阅我上面的评论):

set.seed(1)

## generate similar but larger/more complex toy dataset
a <- sample(letters[1:4], 100, replace = T)
b <- sample(0:1, 10, replace = T)
head((df <- data.frame(a,b)))

  a b
1 b 1
2 b 0
3 c 0
4 d 1
5 a 1
6 d 0

## create a set of contingency tables for proportions 
## of each level of df$a to the others
cTbls  <- lapply(unique(a), function(x) table(df$a==x, df$b))

## apply chi-squared test to each contingency table
results <- lapply(cTbls, prop.test, correct = FALSE)
## preserve names
names(results) <- unique(a)

## only one result displayed for sake of space:
results$b

    2-sample test for equality of proportions without continuity
    correction

data:  X[[i]]
X-squared = 0.18382, df = 1, p-value = 0.6681
alternative hypothesis: two.sided
95 percent confidence interval:
 -0.2557295  0.1638177
sample estimates:
   prop 1    prop 2 
0.4852941 0.5312500 

但是请注意,您可能不想在不纠正多重比较的情况下解释您的 p 值。一个快速的模拟表明,至少有一个测试错误地拒绝原假设的机会可能大大高于 5%(!):

set.seed(11)

sum(
  replicate(1e4, {
    a <- sample(letters[1:4], 100, replace = T)
    b <- sample(0:1, 100, replace = T)
    df <- data.frame(a,b)
    cTbls  <- lapply(unique(a), function(x) table(df$a==x, df$b))
    results <- lapply(cTbls, prop.test, correct = FALSE)
    any(lapply(results, function(x) x$p.value < .05))
  })
) / 1e4
[1] 0.1642
于 2016-06-12T18:09:31.600 回答
1

从统计的角度来看,我并不完全理解这是在做什么,但是这段代码会生成一个列表,其中每个元素都是t.test()您在上面运行的输出:

a <- c("a","a","a","b","b")
b <- c(0,0,1,0,1)
df <- data.frame(a,b)

library(dplyr)
library(tidyr)

dfNew<-df %>% group_by(a) %>% summarise(count = n()) %>% spread(a, count)

lapply(1:ncol(dfNew), function (x) 
  t.test(c(rep(1, dfNew[1,x]), rep(0, length(b)-dfNew[1,x])), b))

这将节省您t.test(foo, bar)连续输入的时间,也消除了对虚拟变量的需要。

编辑:我不认为上述方法保留了列的顺序,只保留了测量为 0 或 1 的值的频率。如果顺序很重要(同样,我不知道此过程的目标),那么您可以使用 dummy 方法并lapply通过data.frame你命名new.

library(dummies)
new <- dummy.data.frame(df, names = "a")

lapply(1:(ncol(new)-1), function(x)
  t.test(new[,x], new[,ncol(new)]))
于 2016-06-12T16:52:31.107 回答