Как уменьшить набор данных, используя минимум и максимум столбцов? Можно ли использовать семейство функций apply? - PullRequest
0 голосов
/ 18 февраля 2020

У меня есть набор данных в этой форме:

  species  date         start.time           end.time              remarks
  A        2020-02-01   2020-02-01 8:00:00   2020-02-01 12:00:00   slow
  A        2020-02-01   2020-02-01 9:00:00   2020-02-02 00:00:00   NA
  A        2020-02-02   2020-02-01 8:00:00   NA                    medium
  A        2020-02-02   NA                   2020-02-01 11:30:00    NA

У меня 20 разных видов и 200 разных дат. Данные практически одинаковы для всех видов.

Как мне сжать данные, чтобы получить минимальное время начала, максимальное время окончания и каждое уникальное замечание для каждого вида и даты? Вывод:

  species  date         start.time   end.time   remarks
  A        2020-02-01   8:00am       12:00am    slow
  A        2020-02-02   8:00am       11:30am    medium

Мне нужно сделать коды в BASE R, чтобы иметь возможность использовать его на компьютере без целых rnet.

Ответы [ 3 ]

1 голос
/ 18 февраля 2020

Вот подход data.table

Он сводится к минимальному-максимальному временному значению для данных и сворачивает все замечания не-NA, используя ; в качестве разделителя для удобства чтения.

library( data.table )

#sample data
DT <- fread("species  date         start.time           end.time              remarks
A        2020-02-01   2020-02-01T8:00:00   2020-02-01T12:00:00   slow
A        2020-02-01   2020-02-01T9:00:00   2020-02-02T00:00:00   NA
A        2020-02-02   2020-02-01T8:00:00   NA                    medium
A        2020-02-02   NA                   2020-02-01T11:30:00    NA")

#set timestamps as posix
cols = c("start.time", "end.time")
DT[, (cols) := lapply( .SD, as.POSIXct, format = "%Y-%m-%dT%H:%M:%S"), .SDcols = cols]

#summarise to desired format
DT[, .(start.time = min(start.time, na.rm = TRUE),
       end.time = max(end.time, na.rm = TRUE),
       remarks = paste0( remarks[!is.na(remarks)], collapse = ";")),
   by = .(date)]

#          date          start.time            end.time remarks
# 1: 2020-02-01 2020-02-01 08:00:00 2020-02-02 00:00:00    slow
# 2: 2020-02-02 2020-02-01 08:00:00 2020-02-01 11:30:00  medium
1 голос
/ 18 февраля 2020

Вот базовое решение R

f <- function(v) {
  data.frame(species = na.omit(unique(v$species)),
             date = na.omit(unique(v$date)),
             start.time = na.omit(sort(v$start.time)[1]),
             end.time = na.omit(sort(v$end.time,decreasing = T)[1]),
             remarks = na.omit(unique(v$remarks)))
}

dfout <- do.call(rbind, c(make.row.names = F,Map(f,split(df,df[c("species","date")]))))

такое, что

> dfout
  species       date         start.time            end.time remarks
1       A 2020-02-01 2020-02-01 8:00:00 2020-02-02 00:00:00    slow
2       A 2020-02-02 2020-02-01 8:00:00 2020-02-01 11:30:00  medium
1 голос
/ 18 февраля 2020

Мы можем преобразовать переменные времени в класс POSIXct, затем для каждой комбинации species и date получить минимальное значение start.time, максимальное значение end.time и получить unique значение remarks.

library(dplyr)

df %>%
  mutate_at(vars(ends_with('time')), as.POSIXct) %>%
  group_by(species, date) %>%
  summarise(start.time = min(start.time, na.rm = TRUE), 
            end.time = max(end.time, na.rm = TRUE), 
            remarks = toString(unique(na.omit(remarks))))


#  species date       start.time          end.time            remarks
#  <fct>   <fct>      <dttm>              <dttm>              <chr>  
#1  A       2020-02-01 2020-02-01 08:00:00 2020-02-02 00:00:00 slow   
#2  A       2020-02-02 2020-02-01 08:00:00 2020-02-01 11:30:00 medium

Делать это в базе R:

#Convert time to POSIXct
df[3:4] <- lapply(df[3:4], as.POSIXct)
#Get min start.time
df1 <- aggregate(start.time~species + date, df, min, na.rm = TRUE, 
                 na.action = "na.pass")
#Get max end.time
df2 <- aggregate(end.time~species + date, df, max, na.rm = TRUE,
                 na.action = "na.pass")
#Get combined remarks
df3 <- aggregate(remarks~species + date, df, function(x) 
            toString(unique(na.omit(x))), na.action = "na.pass")
#merge into one dataset
Reduce(merge, list(df1, df2, df3))

data

df <- structure(list(species = structure(c(1L, 1L, 1L, 1L), .Label = "A", 
class = "factor"), date = structure(c(1L, 1L, 2L, 2L), .Label = c("2020-02-01", 
"2020-02-02"), class = "factor"), start.time = structure(c(1L, 
2L, 1L, NA), .Label = c("2020-02-018:00:00", "2020-02-019:00:00"
), class = "factor"), end.time = structure(c(2L, 3L, NA, 
1L), .Label = c("2020-02-0111:30:00", "2020-02-0112:00:00", 
"2020-02-0200:00:00"), class = "factor"), remarks = structure(c(2L, 
NA, 1L, NA), .Label = c("medium", "slow"), class = "factor")), 
class = "data.frame", row.names = c(NA, -4L)) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...