R语言:通过强度列表首个Strong的索引匹配对应时间的问题
问题解决:获取强度首次为"Strong"对应的时间
我有一个R语言数据框,包含Strength(强度评估列表)和Time(日期/时间列表)两个字段,需要实现:
- 获取每条记录中强度列表首次出现"Strong"的索引
- 根据该索引选取对应的日期/时间
当前代码存在两个问题:
- 仅选取每个时间列表的首个时间
- 本该返回NA的位置返回了
character(0)
原代码
# Data frame: determine time when strength returns. # Serial strength assessments, date-time values for each assessment Some missing values. Some not returning to "Strong" Strength <- c(NA,"Strong; Strong","Unable to assess; Moderate; Moderate; Moderate; Moderate; Moderate; Strong","Moderate; Moderate; Moderate; Moderate; Strong; Strong","Moderate; Strong; Strong; Moderate; Moderate", "Moderate") Time <- c(NA,"2021-04-16 23:50; 2021-04-17 08:35","2021-02-04 13:00; 2021-02-04 14:45; 2021-02-04 16:59; 2021-02-04 19:27; 2021-02-05 08:20; 2021-02-05 20:18; 2021-02-06 11:00","2021-01-23 08:25; 2021-01-23 19:49; 2021-01-24 08:08; 2021-01-24 19:56; 2021-01-25 19:40; 2021-01-26 09:00","2021-01-14 04:46; 2021-01-14 07:33; 2021-01-14 19:47; 2021-01-15 08:48","2021-01-26 09:00") ST <- as.data.frame(cbind(Strength,Time)) view(ST) # Create lists: separate s.list <- lapply(strsplit(ST$Strength, ";"),unlist) t.list <- lapply(strsplit(ST$Time, ";"),unlist) # Determine index of first instance of "Strong" in s.list and apply to t.list (time) ST$time <-mapply(function(x,y) {x[which.max(y==c("Strong"))]}, t.list,s.list) view(ST)
问题分析
- 仅取首个时间的原因:
- 分割后的强度元素带有前导空格(比如
" Strong"),导致y == "Strong"无法匹配到正确值,所有结果都是FALSE which.max(FALSE)会返回1,因此每次都取时间列表的第一个元素
- 分割后的强度元素带有前导空格(比如
- 返回
character(0)的原因:- 当
Strength为NA时,strsplit返回NA,unlist后得到character(0) - 此时
y == "Strong"得到logical(0),which.max返回integer(0),索引取值后得到character(0) - 当强度列表中没有"Strong"时,
which.max同样返回1,但如果时间列表对应位置无有效值,也会出现异常
- 当
解决方案
修改代码,处理分割后的空格,并添加无匹配时返回NA的逻辑:
# 重新构造数据框(避免cbind自动转成因子) ST <- data.frame(Strength = Strength, Time = Time, stringsAsFactors = FALSE) # 分割并去除每个元素的前后空格 s.list <- lapply(strsplit(ST$Strength, ";"), function(x) if (!is.na(x[1])) trimws(x) else NA) t.list <- lapply(strsplit(ST$Time, ";"), function(x) if (!is.na(x[1])) trimws(x) else NA) # 自定义函数:找到首次出现"Strong"的时间,无匹配则返回NA get_first_strong_time <- function(times, strengths) { if (is.na(strengths[1])) return(NA) # 找到第一个"Strong"的索引 idx <- which(strengths == "Strong")[1] # 存在则返回对应时间,否则返回NA if (!is.na(idx)) times[idx] else NA } # 应用函数到每条记录 ST$time <- mapply(get_first_strong_time, t.list, s.list) # 查看结果 view(ST)
说明
- 使用
trimws去除分割后字符串的前后空格,确保匹配"Strong"时不会因为空格失败 - 自定义函数中先判断是否为NA,再查找第一个匹配的索引,无匹配时明确返回
NA - 用
data.frame构造数据框时指定stringsAsFactors = FALSE,避免字符转因子的问题
内容的提问来源于stack exchange,提问作者Mark T
相关产品推荐
相关产品推荐

