在R中引用同一变量中的前一个值,无循环

在R中引用同一变量中的前一个值,无循环,r,R,谢谢你复习我的问题 我试图创建一个新变量,如果满足某些条件,它将从另一个变量获得值;否则,取上一次观察的值 我可以通过运行这样的循环来实现: data <- mtcars data$test <- NA data$test <- as.numeric(data$test) a0 <- Sys.time() for (i in 2:nrow(data)) { ifelse(data$carb[[i]] < 4, data$test[[i]]

谢谢你复习我的问题

我试图创建一个新变量,如果满足某些条件,它将从另一个变量获得值;否则,取上一次观察的值

我可以通过运行这样的循环来实现:

data <- mtcars
data$test <- NA
data$test <- as.numeric(data$test)

a0 <- Sys.time()
for (i in 2:nrow(data)) {

  ifelse(data$carb[[i]] < 4,
         data$test[[i]] <- data[[i-1,'test']],
         data$test[[i]] <- data[[i,'mpg']]
  )
  a1 <- Sys.time()
  per_left <- (i)/nrow(data)
  print(paste("Time left is", round(as.numeric(as.difftime(a1-a0, units = "mins"))/per_left,2),"mins"))  
  
} 
我运行上面的函数,第2行应该采用前面的值-a,而不是默认值0。如果我使用for循环,它将使用“a”

有没有这样的功能?或者我应该如何更新我的函数以使其更快

请告知。
谢谢大家!

我们可以使用
lag
并且
ifelse
已经矢量化。因此,可以使用
ifelse
case\u(当
时)。但是,当存在多个条件时,
case\u当
将更具普遍性

library(dplyr)
out <- data %>% 
    mutate(new = case_when(carb < 4 ~  lag(test), TRUE ~ mpg)) 

对于第二个数据集,也许是这样

library(dplyr)
df1 %>%
      mutate(new_2 = replace(var1, condition, lag(var1[condition])))
-输出

#  ID condition var1 new_2
#1  1     FALSE    a     a
#2  1      TRUE    b  <NA>
#3  1      TRUE    c     b
#4  1      TRUE    d     c
#5  4      TRUE    f     d
#6  5     FALSE    e     e
更新 基于更新的预期输出

df1 %>% 
    group_by(ID) %>%
    mutate(new_2 = lag(var1)) %>% 
    group_by(grp = rleid(condition), .add = TRUE) %>% 
    mutate(new_2 = coalesce(first(new_2), var1)) %>% 
    ungroup %>%
    dplyr::select(-grp)
# A tibble: 6 x 4
#     ID condition var1  new_2
#  <dbl> <lgl>     <chr> <chr>
#1     1 FALSE     a     a    
#2     1 TRUE      b     a    
#3     1 TRUE      c     a    
#4     1 TRUE      d     a    
#5     4 TRUE      f     f    
#6     5 FALSE     e     e    
df1%>%
分组依据(ID)%>%
突变(新_2=滞后(var1))%>%
分组依据(grp=rleid(条件),.add=TRUE)%>%
突变(新_2=结合(第一个(新_2),var1))%>%
解组%>%
dplyr::select(-grp)
#一个tibble:6x4
#ID条件var1 new_2
#         
#1假a
#2 1真正的b a
#3 1真正的c a
#4 1真d a
#5 4真f
#6 5假e

我们可以使用
lag
ifelse
已矢量化。因此,可以使用
ifelse
case\u(当
时)。但是,当存在多个条件时,
case\u当
将更具普遍性

library(dplyr)
out <- data %>% 
    mutate(new = case_when(carb < 4 ~  lag(test), TRUE ~ mpg)) 

对于第二个数据集,也许是这样

library(dplyr)
df1 %>%
      mutate(new_2 = replace(var1, condition, lag(var1[condition])))
-输出

#  ID condition var1 new_2
#1  1     FALSE    a     a
#2  1      TRUE    b  <NA>
#3  1      TRUE    c     b
#4  1      TRUE    d     c
#5  4      TRUE    f     d
#6  5     FALSE    e     e
更新 基于更新的预期输出

df1 %>% 
    group_by(ID) %>%
    mutate(new_2 = lag(var1)) %>% 
    group_by(grp = rleid(condition), .add = TRUE) %>% 
    mutate(new_2 = coalesce(first(new_2), var1)) %>% 
    ungroup %>%
    dplyr::select(-grp)
# A tibble: 6 x 4
#     ID condition var1  new_2
#  <dbl> <lgl>     <chr> <chr>
#1     1 FALSE     a     a    
#2     1 TRUE      b     a    
#3     1 TRUE      c     a    
#4     1 TRUE      d     a    
#5     4 TRUE      f     f    
#6     5 FALSE     e     e    
df1%>%
分组依据(ID)%>%
突变(新_2=滞后(var1))%>%
分组依据(grp=rleid(条件),.add=TRUE)%>%
突变(新_2=结合(第一个(新_2),var1))%>%
解组%>%
dplyr::select(-grp)
#一个tibble:6x4
#ID条件var1 new_2
#         
#1假a
#2 1真正的b a
#3 1真正的c a
#4 1真d a
#5 4真f
#6 5假e
我们可以将lag()函数添加到ifelse条件中:

data$test = ifelse(data$carb < 4, data$test <- lag(data$test), data$test <-  data$mpg)
> data
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb test
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 21.0
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 21.0
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 21.0
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 21.0
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 22.8
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 21.4
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 14.3
Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 14.3
Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 14.3
Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4 19.2
Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4 17.8
Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3 17.8
Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3 17.8
Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3 16.4
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4 10.4
Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4 10.4
Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4 14.7
Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1 14.7
Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2 14.7
Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1 32.4
Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1 30.4
Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2 33.9
AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2 21.5
Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4 13.3
Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2 13.3
Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1 13.3
Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2 19.2
Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2 27.3
Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4 15.8
Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6 19.7
Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8 15.0
Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2 15.0
> 
data$test=ifelse(data$carb<4,data$test
我们可以将lag()函数添加到ifelse条件中:

data$test = ifelse(data$carb < 4, data$test <- lag(data$test), data$test <-  data$mpg)
> data
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb test
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 21.0
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 21.0
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 21.0
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 21.0
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 22.8
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 21.4
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 14.3
Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 14.3
Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 14.3
Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4 19.2
Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4 17.8
Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3 17.8
Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3 17.8
Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3 16.4
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4 10.4
Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4 10.4
Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4 14.7
Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1 14.7
Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2 14.7
Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1 32.4
Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1 30.4
Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2 33.9
AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2 21.5
Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4 13.3
Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2 13.3
Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1 13.3
Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2 19.2
Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2 27.3
Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4 15.8
Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6 19.7
Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8 15.0
Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2 15.0
> 
data$test=ifelse(data$carb<4,data$test

您可以通过获取条件的位置(
数据$carb<4
)在基数R中执行此操作,并通过将这些索引值减去-1来获取要替换的索引

data <- mtcars
data$test <- mtcars$mpg
inds <- which(data$carb < 4)
data$test[inds] <- data$test[inds - 1]

data您可以通过获取条件的位置(
data$carb<4
)在基数R中执行此操作,并通过将这些索引值减去-1来获取要替换的索引

data <- mtcars
data$test <- mtcars$mpg
inds <- which(data$carb < 4)
data$test[inds] <- data$test[inds - 1]

database R中的一个选项是用
if()…else
替换
ifelse
。然而,使用base R的一个更快的解决方案是使用
ifelse
Reduce
的组合。这比OP的解决方案快3.46/.044~78倍。解决方案是:


v2base R中的一个选项是将
ifelse
替换为
if()…else
。然而,使用base R的一个更快的解决方案是使用
ifelse
Reduce
的组合。这比OP的解决方案快3.46/.044~78倍。解决方案是:



v2虽然它们给出了相同的输出,但是您选择使用[[而不是只在这里:[[i-1,'test']]的任何原因都可以显示您需要的预期结果吗
df1%>%mutate(new_2=replace(var1,condition,lag(var1[condition])
知道您的expected输出有点困难。可能是
df1%>%groupby(ID)%%>%mutate(new_2=case_when(condition~lag(var1),TRUE~'0'))
很抱歉造成混淆。让我试试你的建议。非常感谢。我真的很感激。虽然它们给出了相同的输出,但是你为什么选择使用[[而不是只在这里:[[I-1,'test']]”你能显示预期的结果吗
df1%>%mutate(new_2=replace(var1,condition,lag(var1[condition]))
要知道您的expecetd输出有点困难。可能是
df1%>%group\u by(ID)%%>%mutate(new_2=case\u when(condition~lag(var1),TRUE~'0'))
很抱歉造成混淆。让我试试你的建议。非常感谢。我真的很感激你的建议。嗨,谢谢你的建议。我在使用lag时遇到了一个错误,现在将其添加到我的问题中。你能帮我看一下吗?我的错,让我澄清上面所需的输出。但我真的很感谢你的帮助!嗨,谢谢。我运行了另一个测试规则是“如果ID与上面的ID相似且条件为TRUE,则获取上一个值;否则获取新值”df1您好,谢谢您的建议。我在使用lag时遇到了一个错误,现在将其添加到我的问题中。您能帮我看一下吗?我的错,让我澄清上面所需的输出。但我真的非常感谢您的帮助!您好,谢谢。我运行了另一个测试,但它不起作用。规则是如果ID与上面的ID相似且条件为TRUE,则获取上一个值;否则获取新值“df1嗨,谢谢你的建议。我在使用lag时遇到了一个错误,现在将其添加到我的问题中。你能帮我看一下吗?嗨,谢谢你的建议。我在使用lag时遇到了一个错误,现在将其添加到我的问题中。你能帮我看一下吗?如果
mtcars$mpg[1],我不确定这是否有效。”<4
。如果mtcars$mpg[1]<4
,我不确定这是否有效。哇,这真的很有效。我费了好大劲才明白Reduce()但据我所知,它看起来很棒。谢谢你,我很高兴它能为你工作。
?Reduce
可能会解释细节。哇,这真的很好。我费了好大劲才理解Reduce(),但我对它有点了解