Выборка случайным образом с условиями

Моя проблема находится внутри цикла, у меня есть большой набор данных (DF), подмножество которого выглядит так:

ID     Site Species
101     4   x
101     4   y
101     4   z
102     6   x
102     6   z
102     6   a
102     6   b
103     6   a
103     6   z
103     6   c
103     6   x
103     6   y
105     6   x
105     6   y
105     6   a
105     6   z
108     1   x
108     1   a
108     1   c
108     1   z

Я хотел бы выбрать случайным образом, используя каждую итерацию моего цикла (так, i) все ряды человека ID с каждого сайта. Но главное, только один идентификатор с каждого сайта. У меня есть отдельная функция, которая поднаборляет мой большой набор данных для количества сайтов, так что если i=1 тогда только один из вышеуказанных сайтов (например) будет присутствовать в подмножестве.

Если i=3Что касается этого опубликованного примера, то я бы хотел, чтобы все строки по 101, или все строки по 102, 103 или 105 и все по 108.

Я думаю что-то вроде ddply() с sample() должен сделать это, но я не могу получить это случайно.

Любые предложения будут ценны. Спасибо

Джеймс

2 ответа

Решение

Как насчет этого? Я добавил функцию для имитации того, как я думаю, как выглядят ваши данные.

#dependencies
require(plyr)

#function to make data (just to work with)
make_data<-function(id){
  set.seed(id)
  num_sites<-round(runif(1)*3,0)+1
  num_sp<-round(runif(1)*7,0)+1
  sites<-sample(1:10,num_sites,FALSE)
  ldply(sites,function(x)data.frame(sites=x,sp=sample(letters[1:26],num_sp,FALSE)))
}

#make a data frame for example use (as per question)
ids<-100:200
df<-ldply(ids,function(x)data.frame(id=x,make_data(x)))

################################################
# HERE'S THE CODE FOR THE ANSWER               #
# use ddply to summarise by site & sampled ids #
filter<-ddply(df,.(sites),summarise,set=sample(id,1))
# then apply this filter to the original list
ddply(filter,.(sites),.fun=function(x){return(df[df$site==x$sites & df$id==x$set,])})

Я думаю, что вы можете использовать unique чтобы найти все возможные идентификаторы / сайты, а затем образец из уникального и подмножества.

Например, давайте создадим набор данных

# Set the RNG seed for reproducibility
set.seed(12345)
ID <- rep(100:110, c(2, 6, 3, 1, 3, 8, 9, 2, 4, 5, 6))
site <- rep(1:6, c(8, 7, 8, 11, 4, 11))
species <- sample(letters[1:5], length(ID), replace=T)

df <- data.frame(ID=ID, Site=site, Species=species)

Итак, df выглядит так:

> head(df, 15)
    ID Site Species
1  100    1       d
2  100    1       e
3  101    1       d
4  101    1       e
5  101    1       c
6  101    1       a
7  101    1       b
8  101    1       c
9  102    2       d
10 102    2       e
11 102    2       a
12 103    2       a
13 104    2       d
14 104    2       a
15 104    2       b

Обобщая данные, мы имеем:

Site 1 -> 100, 101
Site 2 -> 102, 103, 104
Site 3 -> 105
Site 4 -> 106, 107
Site 5 -> 108
Site 6 -> 109, 110

Теперь, скажем, я хочу выбрать из 3 сайтов

# The number of sites we want to sample
num.sites <- 3
# Find all the sites
all.sites <- unique(df$Site)
# Pick the sites. 
# You may also want to check that num.sites <= length(all.sites)
sites <- sample(all.sites, num.sites)

В этом случае мы выбрали

> sites
[1] 4 5 6

Итак, теперь мы находим идентификаторы, доступные для каждого сайта

# Now find the IDs in each of those sites
# simplify=F is VERY important to ensure we get a list even if every
# site has the same number of IDs
IDs <- sapply(chosen.sites, function(s)
    {
    unique(df$ID[df$Site==s])
    }, simplify=FALSE)

Что дает нам

> IDs
[[1]]
[1] 106 107

[[2]]
[1] 108

[[3]]
[1] 109 110

Теперь выберите один идентификатор на сайт

# NOTE: this assumes the same ID is not found in multiple sites
# but it's easy to deal with the opposite case
# Again, we return a list, because sapply does not seem 
# to play well with data frames... (try it!)
res <- sapply(IDs, function(i)
  {
  chosen.ID <- sample(as.list(i), 1)
  df[df$ID==chosen.ID,]
  }, simplify=FALSE)

# Finally convert the list to a data frame
res <- do.call(rbind, res)


> res
    ID Site Species
24 106    4       d
25 106    4       d
26 106    4       b
27 106    4       d
28 106    4       c
29 106    4       b
30 106    4       c
31 106    4       d
32 106    4       a
35 108    5       b
36 108    5       b
37 108    5       e
38 108    5       e
44 110    6       d
45 110    6       b
46 110    6       b
47 110    6       a
48 110    6       a
49 110    6       a

Итак, все в одной функции

pickSites <- function(df, num.sites)
    {
    all.sites <- unique(df$Site)
    chosen.sites <- sample(all.sites, num.sites)

    IDs <- sapply(chosen.sites, function(s)
        {
        unique(df$ID[df$Site==s])
        }, simplify=FALSE)

    res <- sapply(IDs, function(i)
        {
        chosen.ID <- sample(as.list(i), 1)
        df[df$ID==chosen.ID,]
        }, simplify=FALSE)

    res <- do.call(rbind, res)
    }
Другие вопросы по тегам