我有一个包含数千行的数据框,并选择了2列,例如:
col1 col2
2 11
3 11
4 12
4 1
5 1
6 2
1 3
1 3
2 4
在每个列中,某些值的值重置为1,然后再次重置之前继续累积到某个值。每列中的重置点独立于另一列。我需要的是一个函数检测复位和更新值,在此复位之前,负值从-1到-3 - 对于每列,取决于它自己的复位。所以需要的结果是:
col1 col2
2 -3
3 -2
4 -1
-3 1
-2 1
-1 2
1 3
1 3
2 4
有关如何做到这一点的任何建议吗? (Dplyr解决方案将是最受欢迎的)。
答案 0 :(得分:5)
另一个基础R解决方案:
mydf[] <- lapply(mydf, function(x) {
w <- which(x == 1 & c(0, head(x,-1)) != 1)
x[c(sapply(w, `-`, 3:1))] <- -3:-1
x
})
给出:
> mydf col1 col2 1 2 -3 2 3 -2 3 4 -1 4 -3 1 5 -2 1 6 -1 2 7 1 3 8 1 3 9 2 4
旧答案:
mydf[] <- lapply(mydf, function(x) {
w <- which(x == 1)
i <- c(0, diff(w)) != 1
w <- c(sapply(w[i], `-`, 3:1))
x[w] <- -3:-1
x
})
答案 1 :(得分:4)
这样的事情怎么样?
f <- function(x) {
idx <- which(x == 1 & dplyr::lag(x) != 1);
for (i in 1:length(idx)) x[seq(idx[i] - 3, idx[i] - 1)] <- -3:-1;
return(x);
}
df[] <- lapply(df, f);
# col1 col2
#1 2 -3
#2 3 -2
#3 4 -1
#4 -3 1
#5 -2 1
#6 -1 2
#7 1 3
#8 1 3
#9 2 4
说明:我们定义一个函数f
,它在(列)向量中找到重置点;对于每个重置点,先前的3个条目将替换为-3:-1
。然后,我们将此函数应用于data.frame
的每一列。
df <- read.table(text =
"col1 col2
2 11
3 11
4 12
4 1
5 1
6 2
1 3
1 3
2 4", header = T)
答案 2 :(得分:4)
使用dplyr
和zoo
,您可以执行此操作...
library(zoo)
df2 <- df %>% mutate_all(~pmin(., rollapply(c(diff(.)<0, NA), #find reset point
3, #roll window
function(x) -which(x)[1], #dist to next reset
fill=NA,
align="left"),
na.rm=TRUE)) #only replaces non-NA values
df2
col1 col2
1 2 -3
2 3 -2
3 4 -1
4 -3 1
5 -2 1
6 -1 2
7 1 3
8 1 3
9 2 4
答案 3 :(得分:4)
这是一个基础R方法:
df[] <- lapply(df, function(x) replace(x, which(sign(diff(x)) < 0) - 0:2, -(1:3)))
df
# col1 col2
# 1 2 -3
# 2 3 -2
# 3 4 -1
# 4 -3 1
# 5 -2 1
# 6 -1 2
# 7 1 3
# 8 1 3
# 9 2 4
答案 4 :(得分:0)
如果只有3个滞后,也可能是好的情况:
library(dplyr)
d <- tbl_df(read.table(text = "col1 col2
2 11
3 11
4 12
4 1
5 1
6 2
1 3
1 3
2 4", stringsAsFactors = FALSE, header = TRUE ))
d %>%
mutate_all(funs(case_when((. > lead(., 1) ~ -1L),
(. > lead(., 2) ~ -2L),
(. > lead(., 3) ~ -3L),
TRUE ~ .)))