根据多列中以下行中的值更新行

时间:2018-05-08 09:44:51

标签: r dplyr

我有一个包含数千行的数据框,并选择了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解决方案将是最受欢迎的)。

5 个答案:

答案 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)

使用dplyrzoo,您可以执行此操作...

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 ~ .)))