Заполнение нового фрейма данных сводками из большого набора данных с количеством лет и лет - PullRequest
0 голосов
/ 09 апреля 2019

Я пытаюсь научить себя манипулировать и обобщать большие наборы данных.Я хотел бы создать новый фрейм данных и заполнить его сводными данными о годах, связанных с подсчетом наблюдений по местоположению.Я создал примерный фрейм данных ниже.

example.frame <- data.frame(
                   "Obs.ID" = 1:50, 
                   "Species" = rep("T. rex", 50),
                   "Site" = c(rep("Big Red", 24), rep("Supermax", 26)),
                   "Site.ID" = c(rep("1578", 24), rep("0185", 26)),
                   "Year" = c(1999, 1999, 1999, 2000, 2001, 2002, 2002,
                              2003, 2003, 2003, 2003, 2003, 2003, 2004,
                              2004, 2004, 2004, 2004, 2005, 2005, 2005, 
                              2006, 2006, 2007, 1978, 1978, 1978, 1978,
                              1979, 1979, 1999, 1999, 2000, 2000, 2000,
                              2000, 2000, 2001, 2001, 2001, 2002, 2003,
                              2003, 2003, 2003, 2004, 2005, 2006, 2006,
                              2006),
                   "Count" = c(0, 1, 5, 0, 3, 1, 1, 0, 1, 3, 2, 1, 1, 0,
                               0, 1, 2, 3, 1, 1, 5, 0, 1, 2, 8, 11, 7,
                               2, 3, 1, 1, 0, 2, 5, 6, 0, 1, 2, 1, 1, 0,
                               0, 2, 3, 1, 2, 0, 1, 2, 1),
                   stringsAsFactors = FALSE)

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

Line.ID - уникальный последовательный идентификатор строки во фрейме данных, начинающийся с 1
Site - имя сайта из example.data
Total.years - общее количество уникальных лет, связанных с сайтом
Years.3 - количество лет с как минимум тремя связанными счетами для сайта, включая нули
лет.4 - количество лет с как минимум четырьмя связанными подсчетами для сайта, включая нули
лет.5 - количество лет с как минимум пятью или более связанными подсчетами для сайта,включая нули
Total.pos - общее количество лет с хотя бы одним счетом для сайта выше нуля
Pos.3 - количество лет с не менеетри счета для сайта оve ноль
Pos.4 - количество лет, по крайней мере, с четырьмя счетами для сайта выше нуля
Pos.5 - количество лет, по крайней мере, с пятьюрассчитывает для сайта выше нуля

Новый фрейм данных должен выглядеть следующим образом:

new.frame <- data.frame(
               "Line.ID" = c(1, 2),
               "Site" = c("Big Red", "Supermax"),
               "Total.years" = c(9, 10),
               "Years.3" = c(4, 5),
               "Years.4" = c(2, 3),
               "Years.5" = c(2, 1),
               "Total.pos" = c(8, 8),
               "Pos.3" = c(3, 5),
               "Pos.4" = c(1, 2),
               "Pos.5" = c(1, 0),
               stringsAsFactors = FALSE)

Я думаю, что правильным решением было бы сочетание «summaze» и «group_by»'в dplyr, но я не могу понять, как все это собрать вместе.Я не смог найти ответ на вопрос, который работал бы для этого сценария, поэтому я подумал, что это будет полезно опубликовать.

Последующий вопрос:
Как бы я включил дополнительный слой в созданиеСводная таблица (например, добавление дополнительных видов, встречающихся на тех же участках)?Пример фрейма данных ниже.

example.frame.2 <- data.frame(
                     "Obs.ID" = 1:80,
                     "Species" = c(rep("T. rex", 50),
                                   rep("T. bataar", 30)),
                     "Site" = c(rep("Big Red", 24),
                                rep("Supermax", 26),
                                rep("Big Red", 16),
                                rep("Supermax", 10),
                                rep("Oz", 4)),
                     "Site.ID" = c(rep("1578", 24), rep("0185", 26),
                                   rep("1578", 16), rep("0185", 10),
                                   rep("2115", 4)),
                     "Year" = c(1999, 1999, 1999, 2000, 2001, 2002, 2002,
                                2003, 2003, 2003, 2003, 2003, 2003, 2004,
                                2004, 2004, 2004, 2004, 2005, 2005, 2005,
                                2006, 2006, 2007, 1978, 1978, 1978, 1978,
                                1979, 1979, 1999, 1999, 2000, 2000, 2000,
                                2000, 2000, 2001, 2001, 2001, 2002, 2003,
                                2003, 2003, 2003, 2004, 2005, 2006, 2006,
                                2006, 2003, 2003, 2003, 2003, 2003, 2004,
                                2004, 2004, 2004, 2004, 2005, 2005, 2005,
                                2006, 2006, 2007, 1978, 1978, 1978, 1978,
                                1979, 1979, 1999, 1999, 2000, 2000, 2012,
                                2012, 2012, 2013),
                     "Count" = c(0, 1, 5, 0, 3, 1, 1, 0, 1, 3, 2, 1, 1, 0, 0,
                                 1, 2, 3, 1, 1, 5, 0, 1, 2, 8, 11, 7, 2, 3,
                                 1, 1, 0, 2, 5, 6, 0, 1, 2, 1, 1, 0, 0, 2, 3,
                                 1, 2, 0, 1, 2, 1, 1, 3, 2, 1, 1, 0, 0, 1, 2,
                                 3, 1, 1, 5, 0, 1, 2, 8, 11, 7, 2, 3, 1, 1,
                                 0, 2, 5, 1, 1, 3, 0),
                     stringsAsFactors = FALSE)

Сводный фрейм данных со слоем вида ниже.

new.frame.2 <- data.frame(
                 "Line.ID" = c(1, 2, 3, 4, 5),
                 "Species" = c(rep("T. rex", 2), rep("T. bataar", 3)),
                 "Site" = c("Big Red", "Supermax", "Big Red", "Supermax", "Oz"),
                 "Total.years" = c(9, 10, 5, 4, 2),
                 "Years.3" = c(4, 5, 3, 1, 1),
                 "Years.4" = c(2, 3, 2, 1, 0),
                 "Years.5" = c(2, 1, 2, 0, 0),
                 "Total.pos" = c(8, 8, 5, 4, 1),
                 "Pos.3" = c(3, 5, 3, 1, 1),
                 "Pos.4" = c(1, 2, 1, 1, 0),
                 "Pos.5" = c(1, 0, 1, 0, 0),
                 stringsAsFactors = FALSE)

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

Мы могли бы использовать table для подсчета частоты и сделать это за один раз group_by.

library(dplyr)

example.frame %>%
   group_by(Site) %>%
   summarise(Total_Years = n_distinct(Year), 
             Years.3 = sum(table(Year) >= 3), 
             Years.4 = sum(table(Year) >= 4), 
             Years.5 = sum(table(Year) >= 5), 
             Total.Pos = sum(table(Year[Count > 0]) > 0),
             Pos.3 = sum(table(Year[Count > 0]) >= 3),
             Pos.4 = sum(table(Year[Count > 0]) >= 4),
             Pos.5 = sum(table(Year[Count > 0]) >= 5)) %>%
   ungroup() %>%
   mutate(Line.ID = row_number()) %>%
  select(Line.ID, everything())

#  Line.ID Site     Total_Years Years.3 Years.4 Years.5 Total.Pos Pos.3 Pos.4 Pos.5
#    <int> <chr>          <int>   <int>   <int>   <int>     <int> <int> <int> <int>
#1       1 Big Red            9       4       2       2         8     3     1     1
#2       2 Supermax          10       5       3       1         8     5     2     0

Для второго вопроса нам просто нужно добавить дополнительную group_by переменную Species, и она должна работать.

example.frame.2 %>%
   group_by(Species, Site) %>%
   summarise(Total_Years = n_distinct(Year), 
             Years.3 = sum(table(Year) >= 3), 
             Years.4 = sum(table(Year) >= 4), 
             Years.5 = sum(table(Year) >= 5), 
             Total.Pos = sum(table(Year[Count > 0]) > 0),
             Pos.3 = sum(table(Year[Count > 0]) >= 3),
             Pos.4 = sum(table(Year[Count > 0]) >= 4),
             Pos.5 = sum(table(Year[Count > 0]) >= 5)) %>%
    ungroup() %>%
    mutate(Line.ID = row_number()) %>%
    select(Line.ID, everything())


# Line.ID Species   Site     Total_Years Years.3 Years.4 Years.5 Total.pos Pos.3 Pos.4 Pos.5
#    <int> <chr>     <chr>          <int>   <int>   <int>   <int>     <int> <int> <int> <int>
#1       1 T. bataar Big Red            5       3       2       2         5     3     1     1
#2       2 T. bataar Oz                 2       1       0       0         1     1     0     0
#3       3 T. bataar Supermax           4       1       1       0         4     1     1     0
#4       4 T. rex    Big Red            9       4       2       2         8     3     1     1
#5       5 T. rex    Supermax          10       5       3       1         8     5     2     0
0 голосов
/ 14 апреля 2019

Мы можем сделать это программно (при условии, что нам нужно сделать это для множественных сравнений)

library(data.table)
# set an identifier for values to compare
n1 <- 3:5
# convert the data.frame to data.table, get the Total_Years, Total_pos
# grouped by Site
dt1 <- setDT(example.frame)[, .(Total_Years = uniqueN(Year),
           Total_pos = sum(tabulate(Year[Count > 0]) > 0)), Site]

# grouped by Site, loop through the Year, 
# Year where 'Count' is greater than 0 with lapply
# get the frequency count with tabulate
# check whether it is greater than or equal to values in n1
# get the sum of logical vector inside Map
# melt into long format 
# dcast the data into wide after doing some transformation
# join with the dt1 on Site
dcast(melt(setnames(example.frame[, lapply(list(Year, Year[Count > 0]),
    function(u) Map(function(x, y) sum(x >= y), list(tabulate(u)), n1)), 
      by = Site], 2:3, c("Year", "Pos")), id.var = "Site")[, 
     variable := paste0(variable, ".", n1)], Site ~ variable)[dt1, on = .(Site)]
#       Site Pos.3 Pos.4 Pos.5 Year.3 Year.4 Year.5 Total_Years Total_pos
#1:  Big Red     3     1     1      4      2      2           9         8
#2: Supermax     5     2     0      5      3      1          10         8

Для второго набора данных, добавить «Виды» также в переменную группировки и сделатькак и раньше

dt1 <- setDT(example.frame.2)[, .(Total_Years = uniqueN(Year),
       Total_pos = sum(tabulate(Year[Count > 0]) > 0)), .(Species, Site)]

dcast(melt(setnames(example.frame.2[, lapply(list(Year, Year[Count > 0]), 
 function(u) Map(function(x, y) sum(x >= y), list(tabulate(u)), n1)),
   by = .(Species, Site)], 3:4, c("Year", "Pos")),
   id.var = c("Species", "Site"))[, variable := paste0(variable, ".", n1)], 
     Species + Site ~ variable)[dt1, on = .(Species, Site)]
#     Species     Site Pos.3 Pos.4 Pos.5 Year.3 Year.4 Year.5 Total_Years Total_pos
#1:    T. rex  Big Red     3     1     1      4      2      2           9         8
#2:    T. rex Supermax     5     2     0      5      3      1          10         8
#3: T. bataar  Big Red     3     1     1      3      2      2           5         5
#4: T. bataar Supermax     1     1     0      1      1      0           4         4
#5: T. bataar       Oz     1     0     0      1      0      0           2         1

Также это можно сделать с помощью tidyverse.Лучше построить функцию для повторного использования

library(tidyverse)
countFn <- function(data, grpVars, yearCol, countCol, n) {
          yearCol <- enquo(yearCol)
          countCol <- enquo(countCol)

          yearnm <- paste0("Years.", n)
          posnm <- paste0("Pos.", n)

     d1 <- data %>%
             group_by_at(grpVars) %>%
             summarise(Total_Years = n_distinct(!! yearCol),
                 Total_pos = sum(tabulate((!! yearCol)[(!! countCol)> 0]) > 0))

     data %>% 
         group_by_at(grpVars) %>%
         summarise(Col = list(map(list((!! yearCol), (!! yearCol)[(!!countCol) > 0] ),
                  ~ map2_dfc(list(tabulate(.x)), n, 
                            ~ sum(.x >= .y) ) 







              ) %>% map2_dfc(., list(yearnm, posnm), set_names)


              )) %>%          
                   right_join(d1) %>%
                   unnest(Col)



}

-testing

n1 <- 3:5
countFn(example.frame, "Site", Year, Count, n1)
# A tibble: 2 x 9
#  Site     Total_Years Total_pos Years.3 Years.4 Years.5 Pos.3 Pos.4 Pos.5
#  <chr>          <int>     <int>   <int>   <int>   <int> <int> <int> <int>
#1 Big Red            9         8       4       2       2     3     1     1
#2 Supermax          10         8       5       3       1     5     2     0

countFn(example.frame.2, c("Species", "Site"), Year, Count, n1)
# A tibble: 5 x 10
# Groups:   Species [2]
#  Species   Site     Total_Years Total_pos Years.3 Years.4 Years.5 Pos.3 Pos.4 Pos.5
#  <chr>     <chr>          <int>     <int>   <int>   <int>   <int> <int> <int> <int>
#1 T. bataar Big Red            5         5       3       2       2     3     1     1
#2 T. bataar Oz                 2         1       1       0       0     1     0     0
#3 T. bataar Supermax           4         4       1       1       0     1     1     0
#4 T. rex    Big Red            9         8       4       2       2     3     1     1
#5 T. rex    Supermax          10         8       5       3       1     5     2     0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...