使用dplyr按年份计算总溶解固体占比的技术求助
解决dplyr计算年度TDS占比的问题
我来帮你梳理下代码里的关键问题,再给出修正后的方案,刚好能满足你要的19行2列年度占比数据集需求:
原代码的核心问题
- 错误的提前过滤:你第一步就把
val > 50的数据保留下来,这会丢失大量用来计算占比的基础样本(比如TDS在50-500之间的样本),占比必须基于当年所有TDS样本来计算,不能提前筛除。 - 占比逻辑错误:当前
prop的计算是用单个TDS数值除以当年总和,这是单值在总量中的占比,而你需要的是当年TDS>500的样本数占总样本数的比例。 - 重复冗余的类型转换:每次都写
as.numeric(as.character(val))既麻烦又容易出错,应该提前把val转成数值型。 - 年份提取不够直观:用
cut转成Date类型的年份不如直接提取数字年份方便后续输出。
修正后的完整代码
先确保加载必要的工具包(推荐用lubridate简化日期处理):
if (!require(pacman)) { install.packages('pacman') } pacman::p_load("dplyr", "lubridate")
然后处理数据并计算占比:
# 读取原始数据(保持你的读取逻辑) roadsalt_data <- read.table("QADportaldata_1988-2015.tsv", header=T, sep="\t", fill=T, stringsAsFactors = F) # 预处理:转换日期、把val转为数值型、过滤目标数据 processed_data <- roadsalt_data %>% mutate( stdate = as.Date(stdate), val = as.numeric(val) # 提前转换,避免后续重复操作 ) %>% # 精准筛选1997-2015年的TDS数据 filter( charnam == "Total dissolved solids", year(stdate) %in% 1997:2015 ) %>% select(orgid, stdate, locid, charnam, val) # 保留需要的列 # 计算年度TDS>500的占比 percent_data <- processed_data %>% mutate(year = year(stdate)) %>% # 提取数字年份 group_by(year) %>% summarise( total_samples = n(), # 当年总样本数 tds_over_500 = sum(val > 500, na.rm = TRUE), # 当年TDS>500的样本数(自动处理NA) pct_over_500 = round(tds_over_500 / total_samples * 100, 2) # 计算占比并保留两位小数 ) %>% select(year, pct_over_500) # 只保留需要的两列
关键步骤说明
- 提前转换数值类型:把
val转成数值型后,后续计算不用重复写类型转换代码,同时as.numeric()会自动把非数值的字符转为NA,后续用na.rm=TRUE忽略这些缺失值。 - 精准时间筛选:用
year(stdate) %in% 1997:2015直接锁定你需要的19年,比日期范围更精准。 - 占比逻辑修正:用
n()获取当年总样本数,sum(val>500)统计符合条件的样本数(逻辑值TRUE会被转为1,FALSE转为0),再计算比例。 - 最终结构调整:通过
select()只保留年份和占比,完美得到你要的19行2列数据集。
如果原始数据里val有大量空值或非数值内容,可以在转换时加上na_if()优化:
val = as.numeric(na_if(val, "")) # 将空字符串转为NA
内容的提问来源于stack exchange,提问作者NBE
相关产品推荐
相关产品推荐

