R语言不使用chisq.test()复现卡方检验期望频数表的代码问题求解
R手动实现卡方检验:期望频数计算问题排查
示例数据集构造
首先构造性别与学习模式的列联表数据:
dat <- rbind(c(3, 27), c(33, 9)) rownames(dat) <- c("Studying", "Not-studying") colnames(dat) <- c("Men", "Women") ## 生成的数据集如下: ## Men Women ## Studying 3 27 ## Not-studying 33 9
原代码问题说明
你写的代码存在3个核心问题:
- 赋值逻辑错误:R中
for循环没有返回值,直接将for循环赋值给expected只会得到NULL,需要先提前初始化和dat维度一致的空矩阵 - 计算逻辑错误:期望频数公式是行合计 × 列合计 / 总合计,你写成了对
sum(行元素 × 列合计)求和,逻辑完全错位 - 语法错误:表达式括号不匹配,缺少右闭合括号
修正后的for循环实现
# 第一步:初始化同维度的期望频数矩阵 expected <- matrix(nrow = nrow(dat), ncol = ncol(dat), dimnames = dimnames(dat)) # 第二步:计算总样本量 total <- sum(dat) # 第三步:循环计算每个单元格的期望频数 for(i in 1:nrow(dat)) { row_sum <- sum(dat[i, ]) # 提前算好当前行合计,避免重复计算 for(j in 1:ncol(dat)) { col_sum <- sum(dat[, j]) # 提前算好当前列合计 expected[i,j] <- row_sum * col_sum / total } }
运行后得到的expected结果如下:
Men Women Studying 15 15 Not-studying 21 21
和你给出的示例计算结果一致。
可选:更高效的向量化实现
不需要写for循环,直接用R的向量化运算可以一行代码得到结果:
expected <- rowSums(dat) %o% colSums(dat) / sum(dat)
其中%o%是外积运算符,直接将行合计向量和列合计向量两两相乘得到矩阵,再除以总样本量即可。
内容的提问来源于stack exchange,提问作者JaFranke
相关产品推荐
相关产品推荐

