You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在R中编写函数按特定连续条件统计观测数及排障

解决你的决策树式统计问题与代码报错

首先,我们先拆解你的核心需求:你需要按指定列顺序,依次统计前一列取值为0时当前列取值为1的观测数,以此探究不同列顺序对决策树分支的影响,最后用ggplot2可视化对比结果。原代码的报错和逻辑偏差主要来自两个问题:一是函数逻辑不符合实际需求,二是未处理数据中的NA值。


1. 报错原因分析

你原函数count_no_yes是统计前i列全为1的观测数,完全偏离了“前一列0→当前列1”的统计需求;同时样本数据中存在全NA的列(比如AT列),这会导致apply计算时出现维度异常,触发dim(X) must have a positive length错误。


2. 完整解决方案代码

我们将从数据预处理、函数重定义、场景计算到绘图完整实现你的需求:

步骤1:数据预处理(处理NA值)

由于你的变量是0/1二值变量,我们将所有非第一列的NA替换为0(视为不满足条件),你也可以根据需求选择过滤含NA的观测:

# 将第2-16列的NA替换为0
data[, 2:16] <- lapply(data[, 2:16], function(x) ifelse(is.na(x), 0, x))

步骤2:定义符合需求的统计函数

根据你“决策树分支”的描述,我们提供两种函数供选择:

函数1:统计全局中「前一列0且当前列1」的观测数

适用于你需要统计所有观测中,顺序里上一列是0、当前列是1的数量:

count_prev0_curr1 <- function(data, col_order) {
  # 初始值为总观测数
  counts <- c(nrow(data))
  # 从第2列开始遍历顺序
  for (i in 2:length(col_order)) {
    prev_col <- col_order[i-1]
    curr_col <- col_order[i]
    # 统计符合条件的观测数
    cnt <- sum(data[[prev_col]] == 0 & data[[curr_col]] == 1, na.rm = TRUE)
    counts <- c(counts, cnt)
  }
  return(counts)
}

函数2:统计决策树路径中「前面所有列0且当前列1」的观测数

更贴合决策树的路径筛选逻辑:统计经过前面所有列都为0的筛选后,当前列是1的观测数:

count_allprev0_curr1 <- function(data, col_order) {
  counts <- c(nrow(data))
  # 初始筛选条件:保留所有观测
  filter <- rep(TRUE, nrow(data))
  for (i in 1:length(col_order)) {
    curr_col <- col_order[i]
    # 更新筛选条件:前面所有列都为0
    if (i > 1) {
      filter <- filter & (data[[col_order[i-1]]] == 0)
    }
    # 统计当前筛选集合中当前列是1的数量
    cnt <- sum(filter & (data[[curr_col]] == 1), na.rm = TRUE)
    counts <- c(counts, cnt)
  }
  return(counts)
}

步骤3:计算两个场景的统计结果

# 场景A:原列顺序(第2到16列)
orderA <- colnames(data)[2:16]
countsA <- count_prev0_curr1(data, orderA) # 或选择count_allprev0_curr1
endpoints <- 0:(length(countsA)-1)
scenarioA <- data.frame(endpoint = endpoints, hits = countsA, scenario = "scenarioA")

# 场景B:自定义列顺序
orderB <- colnames(data)[c(9, 10, 11, 5, 6, 8, 3, 2, 4, 13, 12, 7, 14, 15, 16)]
countsB <- count_prev0_curr1(data, orderB) # 对应选择相同函数
scenarioB <- data.frame(endpoint = endpoints, hits = countsB, scenario = "scenarioB")

# 合并场景数据
scenarios <- rbind(scenarioA, scenarioB)

步骤4:用ggplot2绘制对比图

library(ggplot2)
ggplot(scenarios, aes(x = endpoint, y = hits, color = scenario, group = scenario)) +
  geom_point(size = 2) +
  geom_line(linewidth = 1) +
  labs(title = "观测数随列顺序分支的变化", 
       x = "步骤(0为初始总观测数)", 
       y = "符合条件的观测数") +
  theme_minimal()

3. 关键注意事项

  • NA值处理:如果需要过滤含NA的观测,可替换预处理步骤为data <- na.omit(data),但会减少总观测数。
  • 函数选择:根据你的实际需求选择对应函数,函数2更符合决策树的路径式筛选逻辑。
  • 报错解决:新函数直接通过列索引访问数据,避免了apply的维度问题,同时处理了NA值,不会再触发原报错。

内容的提问来源于stack exchange,提问作者Emilie

火山引擎 最新活动