Рассчитать среднее число лиц, присутствующих на каждую дату в R - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть набор данных, который содержит период проживания (от начала.даты до конца.даты) помеченных лиц (ID) на разных сайтах.Моя цель - создать столбец, в котором будет указано среднее число других людей в день, которые также присутствовали на том же сайте (по всему периоду проживания каждого человека).

Для этого мне нужноопределить общее количество лиц, которые присутствовали на сайте на каждую дату, суммированные по общему периоду проживания каждого человека.В конечном итоге я разделю эту сумму на общее количество дней проживания каждого человека для расчета среднего значения.Может ли кто-нибудь помочь мне в этом?

Я рассчитал общее количество дней проживания (total.days), используя lubridate и dplyr

mutate(total.days = end.date - start.date + 1)

    site    ID  start.date  end.date  total.days
1     1   16      5/24/17     6/5/17    13
2     1   46      4/30/17     5/20/17   21  
3     1   26      4/30/17     5/23/17   24
4     1   89      5/5/17      5/13/17   9
5     1   12      5/11/17     5/14/17   4
6     2   14      5/4/17      5/10/17   7
7     2   18      5/9/17      5/29/17   21
8     2   19      5/24/17     6/10/17   18
9     2   39      5/5/17      5/18/17   14

1 Ответ

0 голосов
/ 13 сентября 2018

Прежде всего, всегда желательно предоставить выборку данных в более удобном формате, используя dput(yourData), чтобы другие могли легко восстановить ваши данные.Вот результат dput(), которым вы могли бы поделиться:

> dput(dat)
structure(list(site = c(1, 1, 1, 1, 1, 2, 2, 2, 2), ID = c(16, 
46, 26, 89, 12, 14, 18, 19, 39), start.date = structure(c(17310, 
17286, 17286, 17291, 17297, 17290, 17295, 17310, 17291), class = "Date"), 
end.date = structure(c(17322, 17306, 17309, 17299, 17300, 
17296, 17315, 17327, 17304), class = "Date")), class = "data.frame", row.names = 
c(NA, 
-9L))

Чтобы сделать это легко, нам сначала нужно распаковать start.date и end.date к отдельным датам:

newDat <- data.frame()
for (i in 1:nrow(dat)){
  expand  <-  data.frame(site = dat$site[i],
                         ID = dat$ID[i],
                         Dates = seq.Date(dat$start.date[i], dat$end.date[i], 1))
  newDat <- rbind(newDat, expand)
}

newDat
    site ID      Dates
1      1 16 2017-05-24
2      1 16 2017-05-25
3      1 16 2017-05-26
4      1 16 2017-05-27
5      1 16 2017-05-28
6      1 16 2017-05-29
7      1 16 2017-05-30
. . . 
. . .

Затем мы рассчитываем количество других людей, присутствующих на каждом сайте в каждый день:

individualCount = newDat %>%
                     group_by(site, Dates) %>%
                     summarise(individuals = n_distinct(ID) - 1)
individualCount
# A tibble: 75 x 3
# Groups:   site [?]
    site Dates      individuals
   <dbl> <date>           <int>
 1     1 2017-04-30           1
 2     1 2017-05-01           1
 3     1 2017-05-02           1
 4     1 2017-05-03           1
 5     1 2017-05-04           1
 6     1 2017-05-05           2
 7     1 2017-05-06           2
 8     1 2017-05-07           2
 9     1 2017-05-08           2
 10    1 2017-05-09           2
 # ... with 65 more rows

Затем мы дополняем наши данные новой информацией, используя left_join() и вычисляем требуемое среднее значение:

newDat <- left_join(newDat, individualCount, by = c("site", "Dates")) %>%
            group_by(site, ID) %>%
            summarise(duration = max(Dates) - min(Dates)+1,
                      av.individuals = mean(individuals))
newDat
# A tibble: 9 x 4
# Groups:   site [?]
   site    ID duration av.individuals
  <dbl> <dbl> <time>            <dbl>
1     1    12 4                  0.75
2     1    16 13                 0   
3     1    26 24                 1.42
4     1    46 21                 1.62
5     1    89 9                  1.33
6     2    14 7                  1.14
7     2    18 21                 0.875
8     2    19 18                 0.333
9     2    39 14                 1.14

Последний шаг - снова добавить необходимый столбец в исходный набор данных (dat) с помощью left_join():

dat %>% left_join(newDat, by = c("site", "ID"))
dat
  site ID start.date   end.date   duration av.individuals
1    1 16 2017-05-24 2017-06-05    13 days       0.000000
2    1 46 2017-04-30 2017-05-20    21 days       1.619048
3    1 26 2017-04-30 2017-05-23    24 days       1.416667
4    1 89 2017-05-05 2017-05-13     9 days       2.333333
5    1 12 2017-05-11 2017-05-14     4 days       2.750000
6    2 14 2017-05-04 2017-05-10     7 days       1.142857
7    2 18 2017-05-09 2017-05-29    21 days       0.857143
8    2 19 2017-05-24 2017-06-10    18 days       0.333333
9    2 39 2017-05-05 2017-05-18    14 days       1.142857
...