在R中如何基于相邻行的x变量值生成判断变量z?
解决相邻行x值差异生成z列的问题
我来帮你搞定这个需求!你想要生成的z列逻辑很清晰:第一行设为NA,之后每行如果和前一行的x值不同就取1,相同则取0。你的循环写法出了几个小问题,我先帮你修正循环,再给你推荐更高效的矢量化方法~
先看你的循环问题出在哪
你的两个循环都有关键错误:
- 你用了
length(df),这个返回的是数据框的列数(这里是3),而不是行数!应该用nrow(df)或者length(df$x)来获取行数。 - 第一个循环里,每次都给整个
df$z赋值,最后只会保留最后一次循环的结果,而不是逐行更新。 - 第二个循环里用了
df$z == 1(这是判断操作,不是赋值),正确的赋值应该是df$z[i] <- 1。
修正后的循环写法
先初始化z列为NA,然后从第2行开始逐行判断赋值:
df <- data.frame( x = c(1, 1, 2, 0, 0, 0, 0, 1, 1, 2), y = c(1, 1, 2, 0, 0, 0, 0, 1, 1, 2), z = c(0, 1, 2, 0, 0, 0, 0, 1, 1, 2) ) # 初始化z列,第一行为NA df$z <- NA # 从第2行到最后一行循环 for (i in 2:nrow(df)) { df$z[i] <- ifelse(df$x[i] != df$x[i-1], 1, 0) } # 查看结果 df
运行后就能得到你想要的z列啦。
更高效的矢量化方法(推荐)
在R里,矢量化操作比循环更快更简洁,不用写循环就能搞定:
Base R 方法
用diff()函数计算相邻x的差值,再判断是否不等于0,最后把结果转成整数,前面加NA作为第一行:
df$z <- c(NA, as.integer(diff(df$x) != 0))
dplyr 方法(适合tidyverse用户)
用lag()函数获取前一行的x值,再用case_when()做条件判断:
library(dplyr) df <- df %>% mutate(z = case_when( row_number() == 1 ~ NA_integer_, # 第一行设为NA x != lag(x) ~ 1L, # 和前一行x不同取1 TRUE ~ 0L # 否则取0 ))
这两种方法都能直接得到你期望的结果,和你给出的df_expected完全一致。
内容的提问来源于stack exchange,提问作者Mette




