You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言:为数据框非0值添加占比,排除0值的实现问题

问题:仅为数据框非0数值添加占比,0值保持原样

数据集

response <- c("Best overall response", "Best overall response", "Best overall response", "Disease control(c)",    "Disease control(c)",    "Observed response(b)",  "Observed response(b)")
value <- c("Partial Response", "Progressive Disease", "Stable Disease", "No", "Yes", "No", "Yes")
drug1 <-  c(0, 3, 2, 3, 2, 5, 0)
drug2 <- c(0, 3, 1, 3, 1, 4, 0)
drug3 <- c(0, 1, 3, 1, 3, 4, 0)
drug4 <- c(0, 2, 1, 2, 1, 3, 0)
drug5 <- c(1, 0, 2, 0, 3, 2, 1)

zero_ex_df <- data.frame(response, value)
zero_ex_df <- data.frame(zero_ex_df, drug1)
zero_ex_df <- data.frame(zero_ex_df, drug2)
zero_ex_df <- data.frame(zero_ex_df, drug3)
zero_ex_df <- data.frame(zero_ex_df, drug4)
zero_ex_df <- data.frame(zero_ex_df, drug5)

初始代码(为所有数值添加占比)

该代码会给所有数值(包括0)添加占比,不符合需求:

cnt <- 2
### empty dataframe
df <- data.frame()
### for every instance in esc_table_df_cast besides the first 2 non numeric columns ...
for (i in zero_ex_df[3:length(zero_ex_df)])  {
  ### increase count
  cnt <- cnt + 1
  ### create new varible that totals sum of every column and divides by 3 (since this will always give us the sample size) and divides by the current number and mutiplies by 100 to get a percentage. sprintf if for formatting it adds the % symbol and rounds to 1 decimal
  new <- (sprintf("(%0.1f%%)", (i / (sum(zero_ex_df[cnt]) / 3) * 100)))
  ### pasting the percentage next to the number and appending to empty dataframe
  df <- rbind(df, (paste0(i, new)))
}
## transposing data frame
df <- t(df)

zero_ex_df[3:length(zero_ex_df)] <- df

错误的修改尝试

尝试添加条件判断仅处理非0值,但因逻辑错误未得到正确结果:

cnt <- 2

df <- data.frame()

for (i in zero_ex_df[3:length(zero_ex_df)])  {
  if (i == 0){
    new1 <- i
    df <- rbind(df, new1)
  } else {
    cnt <- cnt + 1
    new <- (sprintf("(%0.1f%%)", (i / (sum(zero_ex_df[cnt]) / 3) * 100)))
    df <- rbind(df, (paste0(i, new)))
  }
}

df <- t(df)

zero_ex_df[3:length(zero_ex_df)] <- df

错误原因分析

  1. 条件判断逻辑错误:if (i == 0)是对整个列进行判断,而非列中的单个元素,只有当整列全为0时才会执行if分支,否则所有元素都走else分支。
  2. cnt计数逻辑错误:仅在else分支递增cnt,导致后续列的分母计算时索引错位,占比结果错误。

正确实现方法

方法1:修正循环逻辑

使用向量操作ifelse对列中每个元素单独判断,同时保证cnt在每次循环都正确递增:

cnt <- 2
df <- data.frame()

# 遍历所有drug列
for (col in zero_ex_df[3:length(zero_ex_df)]) {
  cnt <- cnt + 1
  # 计算当前列的占比分母(样本量)
  denominator <- sum(col) / 3
  # 对每个元素判断:0则保留原值,非0则拼接占比
  processed_col <- ifelse(col == 0, 
                          as.character(col), 
                          paste0(col, sprintf("(%0.1f%%)", (col / denominator) * 100)))
  # 将处理后的列加入临时数据框
  df <- rbind(df, processed_col)
}

# 转置后替换原数据框的drug列
df <- t(df)
zero_ex_df[3:length(zero_ex_df)] <- df

方法2:使用dplyr简化实现(推荐)

利用dplyr的across函数批量处理列,代码更简洁高效:

library(dplyr)

zero_ex_df <- zero_ex_df %>%
  mutate(
    across(
      starts_with("drug"),  # 匹配所有以drug开头的列
      ~ ifelse(.x == 0, 
               as.character(.x), 
               paste0(.x, sprintf("(%0.1f%%)", (.x / (sum(.x)/3)) * 100)))
    )
  )

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 08:48:21