如何提取对应于随机选择的值并获得它们的累积总和?

时间:2016-04-10 01:25:32

标签: r loops dataframe

我们说我现在有一个包含两列的数据框:

df<- data.frame(scores_set1=c(32,45,65,96,45,23,23,14),
scores_set2=c(32,40,60,98,21,23,21,63))

我想随机选择一些行

selected_indeces<- sample(c(1:8), 4, replace = FALSE)

现在我想依次添加selected_indeces的值,这意味着对于第一个selected_indeces我只需要该特定行的值,对于第二个我想要第二行值+第一个选择的value ...对于第n个索引,我想要已经选择的所有值的总和+第n行的值。所以,首先需要一个矩阵来将结果放入

   cumulative_loss<-matrix(rep(NA,8*2),nrow=8,ncol=2) 

然后每个列一个循环,每个selected_index

另一个循环
for (s in 1:ncol(df)) #for each column
     {
    for (i in 1:length(selected_indeces)) #for each randomly selected index
      {
      if (i==1)
        {
       cumulative_loss[i,s]<- df[selected_indeces[i],s]
        }

      if (i > 1)
         {
    cumulative_loss[i,s]<- df[selected_indeces[i],s] +  
      df[selected_indeces[i-1],s]
    }
  }
}
虽然这可能是一种天真的方式来做这样的事情,但事情是,如果(i = 4)只添加第4和第3选择的值,而我希望它添加第一,第二,第三和第四随机选择和把它返还。

2 个答案:

答案 0 :(得分:3)

方便地,cumsum()直接处理data.frames,在这种情况下,它独立地在每个列上运行。因此,我们可以使用索引操作索引所选的df行,并将结果直接传递给cumsum()以获得所需的输出:

set.seed(0L);
sel <- sample(1:8,4L);
sel;
## [1] 8 2 3 6
df[sel,];
##   scores_set1 scores_set2
## 8          14          63
## 2          45          40
## 3          65          60
## 6          23          23
cumsum(df[sel,]);
##   scores_set1 scores_set2
## 8          14          63
## 2          59         103
## 3         124         163
## 6         147         186

要为每列选择不同的索引,我们可以使用apply()

set.seed(0L);
apply(df,2L,function(col) cumsum(col[sample(1:8,4L)]));
##      scores_set1 scores_set2
## [1,]          14          63
## [2,]          59         103
## [3,]         124         126
## [4,]         147         147

如果你想提前计算索引,它会变得有点棘手。这是一种方法:

set.seed(0L);
sels <- replicate(2L,sample(1:8,4L)); sels;
##      [,1] [,2]
## [1,]    8    8
## [2,]    2    2
## [3,]    3    6
## [4,]    6    5
sapply(seq_len(ncol(df)),function(ci) cumsum(df[[ci]][sels[,ci]]));
##      [,1] [,2]
## [1,]   14   63
## [2,]   59  103
## [3,]  124  126
## [4,]  147  147

答案 1 :(得分:2)

以下是使用data.table执行此操作的方法(考虑到您对@ bgoldst&#39的回答的评论:

library(data.table); setDT(df)

#sample 4 elements of each column (i.e., every element of .SD), then cumsum them
df[ , lapply(.SD, function(x) cumsum(sample(x, 4)))]

如果你想为每一列使用不同的索引,我会先预先选择它们:

set.seed(1023)
idx <- lapply(integer(ncol(df)), function(...) sample(nrow(df), 4))
idx
# [[1]] #indices for column 1
# [1] 2 8 6 3
# 
# [[2]] #indices for column 2
# [1] 4 8 5 1

然后稍微修改上面的内容:

df[ , lapply( seq_along(.SD), function(jj) cumsum(.SD[[jj]][ idx[[jj]] ]) )]

这是我用代码功能编写的括号/圆括号中最疯狂的汇编,所以我觉得有点理解它是有道理的:

  • seq_along .SD选出每列的索引编号jj
  • .SD[[jj]]选择j列,idx[[jj]]选择该列的索引,.SD[jj]][idx[jj]]]选择idx[[jj]]j行第二列;这相当于.SD[idx[jj], jj, with = FALSE]
  • 最后,我们cumsum我们为列length(idx[[jj]])选择了jj行。

结果:

#     V1  V2
# 1:  45  98
# 2:  59 161
# 3:  82 182
# 4: 147 214