根据有限的随机数随机选择行

时间:2015-01-09 15:46:31

标签: r

似乎很简单,但我无法弄清楚。

我有一堆动物位置数据(217个人)作为单个数据帧。我试图随机选择每个人的X位置进行进一步分析,但需要注意的是X在6-156的范围内。

所以我试图设置一个循环,首先随机选择6-156范围内的值,然后使用该值(比如56)从第一个动物中随机抽取56个位置,依此类推。

for(i in unique(ANIMALS$ID)){
  sub<-sample(6:156,1)
sub2<-i([sample(nrow(i),sub),])
}

这种方法似乎没有用,所以我尝试调整它......

for(i in unique(ANIMALS$ID)){
  sub<-sample(6:156,1)
  rand<-i[sample(1:nrow(i),sub,replace=FALSE),]
}

这也不起作用..任何建议或以前的帖子都会有所帮助!

数据文件的头部... ANIMALS是df的名称,ID表示唯一的个人

>  FID      X       Y MONTH DAY YEAR HOUR MINUTE SECOND  ELKYR SOURCE ID animalid   
1   0 510313 4813290     9   5 2008   22     30      0 342008     FG  1        1    
2   1 510382 4813296     9   6 2008    1     30      0 342008     FG  1        1    
3   2 510385 4813311     9   6 2008    2      0      0 342008     FG  1        1   
4   3 510385 4813394     9   6 2008    3     30      0 342008     FG  1        1 
5   4 510386 4813292     9   6 2008    2     30      0 342008     FG  1        1
6   5 510386 4813431     9   6 2008    4      1      0 342008     FG  1        1

2 个答案:

答案 0 :(得分:0)

这是使用mapply的一种方式。此函数采用两个列表(或可以强制转换为列表的内容)并将函数FUN应用于相应的元素。

# simulate some data
xy <- data.frame(animal = rep(1:10, each = 10), loc = runif(100))

# calculate number of samples for individual animal
num.samples.per.animal <- sample(3:6, length(unique(xy$animal)), replace = TRUE)

num.samples.per.animal
 [1] 6 3 4 4 6 3 3 6 3 5

# subset random x number of rows from each animal
result <- do.call("rbind", 
                  mapply(num.samples.per.animal, split(xy, f = xy$animal), FUN = function(x, y) {
                    y[sample(1:nrow(y), x),]
                  }, SIMPLIFY = FALSE)
)
result

    animal        loc
7        1 0.99483999
1        1 0.50951321
10       1 0.36505294
6        1 0.34058842
8        1 0.26489107
9        1 0.47418823
13       2 0.27213396
12       2 0.28087775
15       2 0.22130069
23       3 0.33646632
21       3 0.02395097
28       3 0.53079981
29       3 0.85287600
35       4 0.84534073
33       4 0.87370167
31       4 0.85646813
34       4 0.11642335
46       5 0.59624723
48       5 0.15379729
45       5 0.57046122
42       5 0.88799675
44       5 0.62171858
49       5 0.75014593
60       6 0.86915983
54       6 0.03152932
56       6 0.66128549
64       7 0.85420774
70       7 0.89262455
68       7 0.40829671
78       8 0.19073661
72       8 0.20648832
80       8 0.71778913
73       8 0.77883677
75       8 0.37647108
74       8 0.65339300
82       9 0.39957202
85       9 0.31188471
88       9 0.10900795
100     10 0.55282999
95      10 0.10145296
96      10 0.09713218
93      10 0.64900866
94      10 0.76099256

修改

这是另一种(更直接的)方法,当行数小于应分配的样本数时,它也会处理这种情况。

set.seed(357)
result <- do.call("rbind",
                  by(xy, INDICES = xy$animal, FUN = function(x) {
                    avail.obs <- nrow(x)

                    num.rows <- sample(3:15, 1)
                    while (num.rows > avail.obs) {
                      message("Sample to be larger than available data points, repeating sampling.")
                      num.rows <- sample(3:15, 1)
                    }
                    x[sample(1:avail.obs, num.rows), ]
                  }))
result

答案 1 :(得分:0)

我喜欢Stackoverflow因为我学到了很多东西。 @RomanLustrik提供了一个简单的解决方案;我的也很直率:

# simulate some data
xy <- data.frame(animal = rep(1:10, each = 10), loc = runif(100))

newVec <- NULL #Create a blank dataFrame

for(i in unique(xy$animal)){
  #Sample a number between 1 and 10 (or 6 and 156, if you need)
    samp <- sample(1:10, 1) 
  #Determine which rows of dataFrame xy correspond with unique(xy$animal)[i]
    rows <- which(xy$animal == unique(xy$animal)[i]) 
  #From xy, sample samp times from the rows associated with unique(xy$animal)[i]
    newVec1 <- xy[sample(rows, samp, replace = TRUE), ]
  #append everything to the same new dataFrame 
    newVec <- rbind(newVec, newVec1) 
  }