Зацикливание номеров строк из одного фрейма данных для создания новых данных с использованием логических операций в R - PullRequest
0 голосов
/ 07 мая 2020

Я хотел бы извлечь фрейм данных, который показывает сколько лет требуется NInd переменной ( набор данных p1 ) для восстановления из-за некоторой отсеивания который показан в фрейме данных e1 .

У меня есть следующие наборы данных (мои намного больше, но просто чтобы дать вам кое-что поиграть):

# Dataset 1
Batch <- c(2,2,2,2,2,2,2,2,2,2)
Rep <- c(0,0,0,0,0,0,0,0,0,0)
Year <- c(0,0,1,1,2,2,3,3,4,4)
RepSeason <- c(0,0,0,0,0,0,0,0,0,0)
PatchID <- c(17,25,19,16,21,24,23,20,18,33)
Species <- c(0,0,0,0,0,0,0,0,0,0)
Selected <- c(1,1,1,1,1,1,1,1,1,1)
Nculled <- c(811,4068,1755,449,1195,1711,619,4332,457,5883)

e1 <- data.frame(Batch,Rep,Year,RepSeason,PatchID,Species,Selected,Nculled)

# Dataset 2
Batch <- c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2)
Rep <- c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Year <- c(0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2)
RepSeason <- c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
PatchID <- c(17,25,19,16,21,24,23,20,18,33,17,25,19,16,21,24,23,20,18,33,17,25,19,16,21,24,23,20,18,33)
Ncells <- c(6,5,6,4,4,5,6,5,5,5,6,5,6,4,4,5,6,7,3,5,4,4,3,3,4,4,5,5,6,4)
Species <- c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
NInd <- c(656,656,262,350,175,218,919,218,984,875,700,190,93,127,52,54,292,12,43,68,308,1000,98,29,656,656,262,350,175,300)

p1 <- data.frame(Batch, Rep, Year, RepSeason, PatchID, Ncells, Species, NInd)

Набор данных под названием e1 показывает только тот год, когда некоторые выбраковки произошли с популяцией по указанному c PatchID .

Я создал следующий сценарий, который в основном использует каждую строку из e1 для создания номера восстановления . Может быть, есть более простой способ добраться до конца, но это тот, который мне удалось получить ... Когда вы запускаете это, вы работаете с ОДНОЙ строкой e1 , поэтому мы сосредотачиваемся на первой PatchID , а затем выполните некоторые вычисления, чтобы сопоставить это с p1 , и, наконец, я получаю номер с именем Recovery .

Теперь Дело в том, что в моем фреймворке 50 000 строк, поэтому повторение этого снова и снова выглядит довольно утомительным. Вот где я подумал, что al oop может быть полезным. Но я попытался, и безуспешно, как заставить его работать ...

#here is where I would like the loop
e2 <- e1[1,] # Trial for one row only # but the idea is having here a loop that keep doing of comes next for each row

e3 <- e2 %>% 
  select(1,2,4,5)

p2 <- p1[,c(1,2,4,5,3,6,7,8)] # Re-order 

row2 <- which(apply(p2, 1, function(x) return(all(x == e3))))

p3 <- p1 %>% 
  slice(row2) # all years with that particular patch in that particular Batch

#How many times was this patch cull during this replicate?
e4 <- e2[,c(1,2,4,5,3,6,7,8)]

e4 <- e4 %>% 
  select(1,2,3,4)

c_batch <- e1[,c(1,2,4,5,3,6,7,8)]

row <- which(apply(c_batch, 1, function(x) return(all(x == e4))))

c4 <- c_batch %>% 
  slice(row)

# Number of year to recover to 95% that had before culled
c5 <- c4[1,] # extract the first time was culled
c5 <- c5 %>% 
  select(1:5)


row3 <- which(apply(p2, 1, function(x) return(all(x == c5))))

Before <- p2 %>% 
  slice(row3)

NInd <- Before[,8] # Before culling number of individuals
Year2 <- Before[,5] # Year number where first culling happened (that actually the number corresponds to individuals before culling, as the Pop file is developed during reproduction, while Cull file is developed after!)
Percent <- (95*NInd)/100 # 95% recovery we want to achieve would correspond to having 95% of NInd BEFORE culled happened (Year2)

After <- p3 %>% 
  filter(NInd >= Percent & Year > Year2) # Look rows that match number of ind and Year

After2 <- After[1,] # we just want the first year where the recovery was successfully achieved

Recovery <- After2$Year - Before$Year
# no. of years to reach 95% of the population immediately before the cull

Я считаю, что конец должен как-то измениться, чтобы сообщить R, что мы создаем фрейм данных с помощью Recovery, что-то вроде:

Batch <- c(1,1,2,2)
Rep <- c(0,0,0,0)
PatchID <- c(17,25,30,12)
Recovery <- c(1,2,1,5)

Final <- data.frame(Batch, Rep, PatchID, Recovery)

Возможно ли это? ИЛИ это слишком запутано, и мне стоит попробовать другой способ?

1 Ответ

0 голосов
/ 07 мая 2020

Правильно ли решает проблему следующее?

Сначала я добавил уникальный идентификатор к вашим data.frames, чтобы разрешить сопоставление файлов отсева и популяции (это позволяет сэкономить большую часть сложного кода поиска) :

# Add a unique ID for the patch/replicate etc. (as done in the example code)
e1$RepID = paste(e1$Batch, e1$Rep, e1$RepSeason, e1$PatchID, sep = ":")
p1$RepID = paste(p1$Batch, p1$Rep, p1$RepSeason, p1$PatchID, sep = ":")

Если вам нужен быстрый обзор количества отбраковок каждого патча, новый RepID упрощает это:

# How many times was each patch culled?
table(p1$RepID)

Тогда вам нужно al oop для проверки времени восстановления после каждой выбраковки. В моих решениях используется sapply l oop (который также сохраняет идентификаторы RepID, чтобы вы могли сопоставить их с другими метаданными позже):

sapply(unique(e1$RepID), function(rep_id){
    all_cull_events = e1[e1$RepID == rep_id, , drop = F]
    first_year = order(all_cull_events$Year)[1] # The first cull year (assuming data might not be in temporal order)
    first_cull_event = all_cull_events[first_year, ] # The row corresponding to the first cull event 

    population_counts = p1[p1$RepID == first_cull_event$RepID, ] # The population counts for this plot/replicate
    population_counts = population_counts[order(population_counts$Year), ] # Order by year (assuming data might not be in temporal order)
    pop_at_first_cull_event = population_counts[population_counts$Year == first_cull_event$Year, "NInd"]
    population_counts_after_cull = population_counts[population_counts$Year > first_cull_event$Year, , drop = F]
    years_to_recovery = which(population_counts_after_cull$NInd >= (pop_at_first_cull_event * .95))[1] # First year to pass 95% threshold
    return(years_to_recovery)
})
2:0:0:17 2:0:0:25 2:0:0:19 2:0:0:16 2:0:0:21 2:0:0:24 2:0:0:23 2:0:0:20 2:0:0:18 2:0:0:33 
       1        2        1       NA       NA       NA       NA       NA       NA       NA 

(вывод содержит некоторые NA, потому что первый год выбраковки находился за пределами диапазона подсчета населения в данных, которые вы нам предоставили)

Пожалуйста, сравните это с ожидаемым результатом. Были некоторые аспекты вопроса и примера кода, которые были неясны (см. Комментарии).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...