R语言循环日期双条件判断问题:<运算符异常排查
嗨,我来帮你搞定这个问题!
问题根源分析
你遇到的<运算符失效问题,核心原因是**datum列是普通字符串格式**,不是R能识别的日期时间类型。直接拿字符串做大小比较时,R会按字符的字典顺序判断(比如"13.10.2017"会被认为比"31.10.2017"小,但实际日期它更早),这完全不符合你要的时间先后逻辑。
另外你的循环还有个小坑:如果i从1开始遍历,i-1就会变成0,超出数据的索引范围,所以得从第2行开始才行。
解决方案
下面给你两种实现方式,优先推荐向量化操作(R里这种方式比循环更高效、更易读):
第一步:先把数据格式转对
首先得把字符格式的日期转换成POSIXct类型,同时把用逗号分隔的小数改成R能识别的点分隔:
# 转换日期时间格式,%d代表日、%m代表月、%Y代表年、%H/%M代表时分 dataset$datum <- as.POSIXct(dataset$datum, format = "%d.%m.%Y %H:%M") # 把逗号小数转成点小数,再转成数值型 dataset$indiv_scores <- as.numeric(gsub(",", ".", dataset$indiv_scores))
方式一:向量化操作(推荐)
用R的向量特性直接处理,不用写循环:
# 先初始化indiv_scores2为indiv_scores的副本 dataset$indiv_scores2 <- dataset$indiv_scores # 定义双条件:touchpoint_type是"b",且当前行日期早于上一行日期 condition <- dataset$touchpoint_type == "b" & dataset$datum < dplyr::lag(dataset$datum) # 给满足条件的行赋值:indiv_scores乘2 dataset$indiv_scores2[condition] <- dataset$indiv_scores[condition] * 2
如果没装dplyr包,用基础R也能实现类似的lag效果:
# 基础R版的条件判断 condition <- dataset$touchpoint_type == "b" & c(FALSE, dataset$datum[-1] < dataset$datum[-nrow(dataset)])
方式二:修正后的循环实现
如果你一定要用循环,那修正后的代码如下:
# 先初始化indiv_scores2 dataset$indiv_scores2 <- dataset$indiv_scores # 从第2行开始遍历,因为第1行没有上一行数据 for (i in 2:nrow(dataset)) { # 同时满足两个条件才执行赋值 if (dataset$touchpoint_type[i] == "b" && dataset$datum[i] < dataset$datum[i-1]) { dataset$indiv_scores2[i] <- dataset$indiv_scores[i] * 2 } }
测试结果
用你给出的测试数据运行后,就能得到你想要的结果:
id datum touchpoint_type indiv_scores indiv_scores2
1 2017-10-31 05:09:00 a 1.7 1.7
2 2017-10-13 03:19:00 b 0.1 0.2
3 2017-09-10 14:26:00 a 3.0 3.0
内容的提问来源于stack exchange,提问作者user9220457
相关产品推荐
相关产品推荐

