检查前一行,并找出R中的数字何时变为零

xa9qqrwz  于 2023-05-26  发布在  其他
关注(0)|答案(3)|浏览(137)

我有这样一个数据:

d <- data.frame(
  ab = c(3, 4, 2, 6),
  dur_1 = c(32, 1, 3, 4),
  dur_2 = c(27, 9, 26, 5),
  dur_3 = c(25, 8, 21, 48),
  dur_5 = c(0, 4, 0, 42),
  dur_6 = c(0, 0, 0, 0),
  dur_7 = c(0, 0, 0, 0),
  cd = c(45, 67, 34, 78)
)

我想做的是创建一个新列pre_durpre_dur是以dur_开始的变量的前几行的最后一个非负值。因此,要获得pre_dur,请扫描前一行中的dur_变量,找到数字开始变为零的位置。最后一个非负数就是我想要的值。
我的预期输出应该是这样的:

d1<-data.frame(ab=c(3,4,2,6),
               dur_1=c(32,1,3,4),
               dur_2=c(27,9,26,5),
               dur_3=c(25,8,21,48),
               dur_5=c(0,4,0,42),
               dur_6=c(0,0,0,0),
               dur_7=c(0,0,0,0),
               cd=c(45,67,34,78),
               pre_dur=c(NA,25,4,21))

实际上下面的代码工作:

d1 <- d %>%
  mutate(pre_dur = case_when(lag(dur_7) > 0 ~ lag(dur_7),
                             lag(dur_6) > 0 ~ lag(dur_6),
                             lag(dur_5) > 0 ~ lag(dur_5),
                             lag(dur_3) > 0 ~ lag(dur_3),
                             lag(dur_2) > 0 ~ lag(dur_2),
                             lag(dur_1) > 0 ~ lag(dur_1),
                             TRUE ~ NA_real_))

但在我的实际数据中,dur_后面的自然数是可以改变的。所以我需要一个通用代码。如何做到这一点?

enyaitl3

enyaitl31#

这个解决方案怎么样?

library(tidyverse)
temp <- d %>% 
  pivot_longer(-ab) %>% 
  group_by(ab) %>% 
  mutate(out = ifelse(value == 0, lag(value), 0)) %>% 
  filter(out != 0) 
  
# bind_cols(d,  pre_dur = c(NA, temp$out[2:nrow(temp)]))

bind_cols(d,  pre_dur = lag(temp$out))

这假设一旦一个值下降到0,那么它就不会增加。如果不是这种情况,那么ifelse语句需要捕获它。

swvgeqrz

swvgeqrz2#

首先,找到每个组的值,然后将其滞后一次。我们可以使用rowwise()来实现,但是将其转换为长格式并再转换回来可能更快,可读性更强。即

library(dplyr)
library(tidyr)

d |>
    pivot_longer(starts_with("dur")) |>
    mutate(pre_dur = last(value[value > 0]), .by = "ab") |>
    pivot_wider() |>
    mutate(pre_dur = lag(pre_dur))
# A tibble: 4 × 9
     ab    cd pre_dur dur_1 dur_2 dur_3 dur_5 dur_6 dur_7
  <dbl> <dbl>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     3    45      NA    32    27    25     0     0     0
2     4    67      25     1     9     8     4     0     0
3     2    34       4     3    26    21     0     0     0
4     6    78      21     4     5    48    42     0     0
sxissh06

sxissh063#

在base中使用max.collast的方法。

i <- which(startsWith(names(d), "dur"))
j <- max.col(d[i] > 0, "last")
cbind(d, pre_dur = c(NA, d[cbind(seq_len(nrow(d)), i[j])][-nrow(d)]))
#  ab dur_1 dur_2 dur_3 dur_5 dur_6 dur_7 cd pre_dur
#1  3    32    27    25     0     0     0 45      NA
#2  4     1     9     8     4     0     0 67      25
#3  2     3    26    21     0     0     0 34       4
#4  6     4     5    48    42     0     0 78      21

相关问题