2014-01-15 16 views
0

Моя проблема сидит внутри цикла, у меня есть большой набор данных (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

Можете ли вы объяснить, почему 'я = 3' означает, что эти' ID's должны быть выбраны и почему '108' отличается от' 102, 103 , 105'? Не могли бы вы показать код, чтобы проиллюстрировать, что вы делаете, какую-то общую настройку. Неясно, что это такое. –

+0

ОК, извините, вот еще какой-то контекст.Я загружаю генерацию кривых накопления видов, используя specaccum() для разных номеров удаленных камер (столбец ID) и разных номеров сайтов (столбец сайта). Поэтому мне нужно, чтобы на одном сайте кривые для одной камеры, двух камер и т. Д., Затем для двух сайтов, кривых для одной камеры, двух камер и т. Д. Мой первый цикл: для (l in 1: length (sitelist)), подмножества в l возможных сайтов и создает список всех возможных камер на этих сайтах. Мой следующий вложенный цикл: for (i in 1: l) - это то, где я хочу пробовать одну камеру, две камеры (с разных сайтов) и т. Д. – user3122022

+0

108 отличается от 102, 103 и 105, потому что он находится на другом сайте (Столбец сайта). Я бы хотел выбрать наугад, один идентификатор с каждого Сайта. Набор данных, который я предоставил, показывает итерацию i = 3 (3 Сайта), другие итерации i (больше сайтов) содержат в них много ID, но я все же хочу только один идентификатор с каждого Сайта независимо от того, насколько велика i (то есть как многие сайты есть). Надеюсь, это имеет смысл. – user3122022

ответ

0

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

#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,])}) 
+0

спасибо, оба ответа велики, но я пошел с этим, потому что это всего лишь 2 строки кода. – user3122022

1

Я думаю, что вы можете использовать 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) 

Так, ДФ выглядит как:

> 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) 
    } 
Смежные вопросы