【问题标题】:Dataframe: column, that checks for each row the value of the previos row and enters value数据框:列,检查每一行的前一行的值并输入值
【发布时间】:2014-12-22 19:34:41
【问题描述】:

我确实尝试了很多来解决以下问题,并且我已经阅读了很多关于它的内容。但是,我仍然无法管理它

看这个例子:

time <- sample(1:300, 20)
test <- c (0,0,0, NA, 0, 0, 3, 0, 0, NA, 0,0, 3, 0, 0, NA, 0, 0, 3, 0)
take <- rep(NA, 20)
df <-data.frame(time, test, take)
> head(df, 8)
  time test take
1  271    0   NA
2  147    0   NA
3  277    0   NA
4  247   NA   NA
5   82    0   NA
6  133    0   NA
7  231    3   NA
8  110    0   NA

现在我想在最后(采取)列中输入值。那里的值取决于第二列(测试)中的条件。如果它是 NA 或 3,它可以保持为空。到目前为止还好, 但我的问题是值 0。如果前一行的值为 0,则应将“a”放入该行,如果为 3,则应放入“b”,其余为“c”。

因此输出应如下所示:

head(df, 8)
      time test take
    1  271    0   c
    2  147    0   a
    3  277    0   a
    4  247   NA   NA
    5   82    0   c
    6  133    0   a
    7  231    3   NA
    8  110    0   b

感谢您的帮助!

【问题讨论】:

    标签: r loops if-statement dataframe


    【解决方案1】:

    试试:

    is0<-which(df$test==0) # indices of test elements = 0
    df[is0,"take"]<-"c" # for each test=0, put take="c", as it is the "default" value
    for (i in setdiff(is0,1)){ # for each test=0 that is not the first one (because the first row doesn't have a previous row)
        if((i-1) %in% is0) df$take[i]<-"a" else if(df$test[i-1]==3 & !is.na(df$test[i-1])) df$take[i]<-"b" # if in the previous row test=0 then take="a", if it is 3 (and not NA), take="b"
    }
    

    【讨论】:

      【解决方案2】:

      使用包dplyr,您可以将您的问题分成两部分。

      第 1 部分:编写一个封装逻辑的函数,以根据前面的行填写 take

      return_value_based_on_previous_row <- function(x, lagged) {
      
          if (is.na(x) | x == 3) {
              temp = NA
          } else {
      
              if (is.na(lagged)) {
                  temp = "c"
              } else if (lagged == 0) {
               temp = "a"
              } else if (lagged == 3) {
               temp = "b"
              } 
      
          }
      
          return(as.character(temp))
      
      }
      

      第 2 部分:使用 lagmutate 逐行处理 df

      df <-
          df %>% 
          mutate(lag_test = lag(test)) %>% # make temp column which contains previous value of test
          rowwise() %>% # makes the following mutate work on each row separately
          mutate(take = return_value_based_on_previous_row(test, lag_test)) %>%
          select(-lag_test) #remove temp column
      

      给出:

      > df
         time test take
      1   164    0    c
      2    36    0    a
      3   279    0    a
      4   255   NA   NA
      5   241    0    c
      6   188    0    a
      7   117    3   NA
      8    75    0    b
      9    60    0    a
      10  175   NA   NA
      11  238    0    c
      12  184    0    a
      13  272    3   NA
      14  215    0    b
      15   49    0    a
      16  204   NA   NA
      17  291    0    c
      18  218    0    a
      19  197    3   NA
      20  138    0    b
      

      【讨论】:

        【解决方案3】:

        你也可以

        indx <- c(FALSE,!df$test[-nrow(df)] & !is.na(df$test)[-nrow(df)])
        indx1 <- c(FALSE,df$test[-nrow(df)]==3 & !is.na(df$test)[-nrow(df)])
        indx2 <- df$test==3|is.na(df$test)
        
        df$take <- c('c','a','b', NA)[as.numeric(factor(1+2*indx+4*indx1+8*indx2))]
        
         df$take
         #[1] "c" "a" "a" NA  "c" "a" NA  "b" "a" NA  "c" "a" NA  "b" "a" NA  "c" "a" NA 
         #[20] "b"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-06-12
          • 1970-01-01
          • 2016-03-21
          • 2021-11-23
          • 1970-01-01
          • 2018-02-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多