如何将数据帧列中的所有先前观测值按组迭代地除以最后一个观测值,然后将结果存储在R中

如何将数据帧列中的所有先前观测值按组迭代地除以最后一个观测值,然后将结果存储在R中,r,iteration,grouping,R,Iteration,Grouping,我有以下数据框: data <- data.frame("Group" = c(1,1,1,1,1,1,1,1,2,2,2,2), "Days" = c(1,2,3,4,5,6,7,8,1,2,3,4), "Num" = c(10,12,23,30,34,40,50,60,2,4,8,12)) 然后只保留值为2的行,因为我不关心其他行(我希望值大于或等于2,最接近2),并返回该值的日期,也就是4。然后,转到50并执行以下操作: Day Num Res 6 50/40 1.25 5 5

我有以下数据框:

data <- data.frame("Group" = c(1,1,1,1,1,1,1,1,2,2,2,2), 
"Days" = c(1,2,3,4,5,6,7,8,1,2,3,4), "Num" = c(10,12,23,30,34,40,50,60,2,4,8,12))
然后只保留值为2的行,因为我不关心其他行(我希望值大于或等于2,最接近2),并返回该值的日期,也就是4。然后,转到50并执行以下操作:

Day Num Res
6 50/40  1.25
5 50/34  1.47
4 50/30  1.67
3 50/23  2.17
2 50/12  4.17
1 50/10  5
然后只保留值为2.17的行,并返回该值的日期,也就是3。然后,继续到40,再做同样的事情,继续到34,然后30,然后23,然后12,最后一个值(或第1天的值),我不在乎。然后转到下一组的最后一个值(12),并对该组重复相同的方法(12/8,12/4,12/2;8/4,8/2;4/2)

我希望存储这些分区的结果,但仅存储大于或等于2的最新结果。我还想回到取得成果的那一天。基本上,我试图计算每天加倍的时间。我还需要按组对其进行分组。通常情况下,我会使用dplyr来实现这一点,但我不确定如何将一个循环与dyplr连接起来,以利用group_by。此外,我可能忽略了lapply或其一些变体。理想情况下,我预期的结果数据框如下:

data2 <- data.frame(divres = c(NA,NA,2.3,2.5,2.833333333,3.333333333,2.173913043,2,NA,2,2,3), 
obs_n =c(NA,NA,1,2,2,2,3,4,NA,1,2,2))

data3 <- bind_cols(data, data2)

data2您可以修改
division
函数来处理向量并返回一个包含两列
divres
ind
的数据帧。后者是用于计算
obs\n
的行索引,如下所示:

    division <- function(x){
  lenx <- length(x)
  y    <- vector(mode="numeric", length = lenx)
  z    <- vector(mode="numeric", length = lenx)
  for (i in lenx:1){
    y[i] <- ifelse(length(which(x[i]/x[1:i]>=2))==0,NA,x[i]/x[1:i] [max(which(x[i]/x[1:i]>=2))])
    z[i] <- ifelse(is.na(y[i]),NA,max(which(x[i]/x[1:i]>=2)))
  }
  df <- data.frame(divres = y, ind = z)
  return(df)
}
使用
cbind
将上述输出与数据帧
data1
组合,使用
pipes
mutate
from
dplyr
使用
ind
查找
Day
中的
obs\n
值,选择适当的列以生成所需的数据帧
data2


您可以创建一个带有for循环的函数,以获得所需的日期,如下所示。然后用它来获得一个dplyr突变中的divres

obs_n <- function(x, days) {
  lst <- list()
  for(i in length(x):1){
    obs <- days[which(rev(x[i]/x[(i-1):1]) >= 2)]
    if(length(obs)==0)
     lst[[i]] <- NA
    else
      lst[[i]] <- max(obs)
  }
  unlist(lst)
}


当你说“除以前面的所有值”时,这是否意味着在第一次迭代中,你从
60
开始,然后(除以前面的所有值)执行
60/50/40/34/30/23/12/10
(即
1.065644e-08
)?这对我来说有点奇怪。。。我可能是在逐字逐句地阅读你的文章。我认为
dplyr
足够简单,包括
分组
,我建议你只讨论单个组的单个向量,比如
c(10,12,23,30,34,40,50,60)
,并逐字解释你对该向量的预期结果,无论是内部还是外部,我现在就编辑这个问题,让它更清晰。哈哈,你说得对。我太累了…所以打个盹儿,但有趣的是,,,,@Maggie我想你的问题可能已经改变了。我很好奇这个解决方案是否正是你想要的。@Maggie你能澄清一下你是如何计算obs\n的吗?
?谢谢你写这篇文章,我会在我的大脑工作时再检查一遍,然后再给你回复。至于obs_n,这是2+结果发生的日子。因此,例如,当除以60时,在第4天获得2.0的值,因此理想情况下,循环将返回4作为obs_n的值。如果除以50,则第3天的结果为2.17,因此这将是返回给obs_n的值。我不知道这是否有意义。既然我写了这个,别告诉我你会怎么做。我想自己试试,如果我被难倒了,我会回来的!感谢您的评论,我确认这与我的数据相符。我将继续学习,以便能够完全理解循环的结构及其工作原理。谢谢您的回答。目前它对我不起作用,但我确信这是因为我将它错误地应用于我的实际数据。我将在本周末对此进行更多的研究,以了解问题所在。我发现您的实际数据可能与您提供的示例数据有所不同。
division <- function(x){
  if(x>=2){
    return(x)
  } else {
    return(FALSE)
  }
}
for (i in 1:nrow(data)){
   data$test[i]<- division(data$test[i])
}

    division <- function(x){
  lenx <- length(x)
  y    <- vector(mode="numeric", length = lenx)
  z    <- vector(mode="numeric", length = lenx)
  for (i in lenx:1){
    y[i] <- ifelse(length(which(x[i]/x[1:i]>=2))==0,NA,x[i]/x[1:i] [max(which(x[i]/x[1:i]>=2))])
    z[i] <- ifelse(is.na(y[i]),NA,max(which(x[i]/x[1:i]>=2)))
  }
  df <- data.frame(divres = y, ind = z)
  return(df)
}
> division(data$Num)
     divres ind
1        NA  NA
2        NA  NA
3  2.300000   1
4  2.500000   2
5  2.833333   2
6  3.333333   2
7  2.173913   3
8  2.000000   4
9        NA  NA
10 2.000000   9
11 2.000000  10
12 3.000000  10
data2 <- cbind.data.frame(data, division(data$Num)) %>% mutate(obs_n = Days[ind]) %>% select(-ind)
> data2
   Group Days Num   divres obs_n
1      1    1  10       NA    NA
2      1    2  12       NA    NA
3      1    3  23 2.300000     1
4      1    4  30 2.500000     2
5      1    5  34 2.833333     2
6      1    6  40 3.333333     2
7      1    7  50 2.173913     3
8      1    8  60 2.000000     4
9      2    1   2       NA    NA
10     2    2   4 2.000000     1
11     2    3   8 2.000000     2
12     2    4  12 3.000000     2
obs_n <- function(x, days) {
  lst <- list()
  for(i in length(x):1){
    obs <- days[which(rev(x[i]/x[(i-1):1]) >= 2)]
    if(length(obs)==0)
     lst[[i]] <- NA
    else
      lst[[i]] <- max(obs)
  }
  unlist(lst)
}
library(dplyr)

data %>%
  group_by(Group) %>%
  mutate(obs_n=obs_n(Num, Days), divres=Num/Num[dense_rank(obs_n)])
# A tibble: 12 x 5
# Groups:   Group [2]
   Group  Days   Num obs_n divres
   <dbl> <dbl> <dbl> <dbl>  <dbl>
 1     1     1    10    NA  NA   
 2     1     2    12    NA  NA   
 3     1     3    23     1   2.3 
 4     1     4    30     2   2.5 
 5     1     5    34     2   2.83
 6     1     6    40     2   3.33
 7     1     7    50     3   2.17
 8     1     8    60     4   2   
 9     2     1     2    NA  NA   
10     2     2     4     1   2   
11     2     3     8     2   2   
12     2     4    12     2   3
x <- c(NA, NA, 1,2,2,4,6)
dplyr::dense_rank(x)
# [1] NA, NA, 1 2 2 3 4
rank(x)
[1] 6.0 7.0 1.0 2.5 2.5 4.0 5.0