R:一步完成具有不同功能的聚合数据表

时间:2018-04-04 12:46:38

标签: r data.table aggregate

我有一个数据表my_table,其中包含数字,字符和日期(POSIXct)列。现在我需要aggregate按日期,每个日期的数字列应由mean汇总,字符和日期列只有一个可用的值(让我们说第一次出现)。我是这样的:

  name          date    value
"test"    2018-04-04        1
"test"    2018-04-04        2
"test"    2018-04-05        8
"test"    2018-04-06        3

我希望有这个:

  name          date    value
"test"    2018-04-04      1.5
"test"    2018-04-05      8.0
"test"    2018-04-06      3.0

我的方法是:

new_table <- aggregate(my_table, by=list(my_table$date), FUN=mean)

导致:

name       date   value
  NA  2018-04-04    1.5
  NA  2018-04-05    8.0
  NA  2018-04-06    3.0

和一堆警告,因为name不是数字。我怎么能告诉函数只使用"test"而不是name的{​​{1}}出现的一个(或者第一个,我不介意)?

让事情变得更难:在我的实际情况中,实际上有很多列需​​要使用均值(如果它们是数字)或第一次出现(如果它们是NAcharacter)。

3 个答案:

答案 0 :(得分:1)

方法1

使用aggregate的基础R解决方案:

df <- transform(df, date = as.POSIXct(date))
aggregate(value ~ date + name, data = df, FUN = mean);
#date name value
#1 2018-04-04 test   1.5
#2 2018-04-05 test   8.0
#3 2018-04-06 test   3.0

如果您有许多列不想明确列出,可以使用:

aggregate(value ~ ., data = df, FUN = mean);

.表示df 中的所有列,但 value除外。

方法2

tidyverse解决方案使用group_bysummarise

library(tidyverse)
df %>%
    mutate(date = as.POSIXct(date)) %>%
    group_by(date, name) %>%
    summarise(value = mean(value))
## A tibble: 3 x 3
## Groups:   date [?]
#  date                name  value
#  <dttm>              <fct> <dbl>
#1 2018-04-04 00:00:00 test   1.50
#2 2018-04-05 00:00:00 test   8.00
#3 2018-04-06 00:00:00 test   3.00

你的标题有点误导:为什么“不同的功能”?我假设你的意思是不同的列。如果您 要求汇总应用不同的功能,您可以执行以下操作:

aggregate(value ~ date + name, data = df, FUN = function(x) c(mean = mean(x), sd = sd(x)));
#        date name value.mean  value.sd
#1 2018-04-04 test  1.5000000 0.7071068
#2 2018-04-05 test  8.0000000        NA
#3 2018-04-06 test  3.0000000        NA

样本数据

df <- read.table(text =
    "  name          date    value
test    2018-04-04        1
test    2018-04-04        2
test    2018-04-05        8
test    2018-04-06        3", header = T)

答案 1 :(得分:1)

您可以根据变量定义自己的汇总函数来执行您想要的操作。类

my_table <- read.table(text =
                       "  name          date    value
                         test    2018-04-04        1
                         test    2018-04-04        2
                         test    2018-04-05        8
                         test    2018-04-06        3", 
                       header = T)

my_summarise <- function(x){
  if(is.numeric(x)) mean(x)
  else if(is.character(x)) x[1]
  else if(is.factor(x)) x[1]
  else if('POSIXct' %in% class(x)) x[1]
}

setDT(my_table)

my_table[, lapply(.SD, my_summarise), by = date]

#          date name value
# 1: 2018-04-04 test   1.5
# 2: 2018-04-05 test   8.0
# 3: 2018-04-06 test   3.0

编辑:实际上没有必要。您可以这样做以获得相同的结果。

my_table[, .(name, mean(value)), by = date]

答案 2 :(得分:0)

如果您实际上使用的是data.table,那么这就是聚合列的简便方法。从具有多个字符和数字列的数据集开始:

library(data.table)

my_table <- data.table(
  name1  = letters[1:4],
  name2  = LETTERS[23:26],
  date   = as.POSIXct(c("2018-04-04", "2018-04-04", "2018-04-05", "2018-04-06")),
  value1 = c(1, 2, 8, 3),
  value2 = c(9, 4, 2, 5)
)

my_table
#    name1 name2       date value1 value2
# 1:     a     W 2018-04-04      1      9
# 2:     b     X 2018-04-04      2      4
# 3:     c     Y 2018-04-05      8      2
# 4:     d     Z 2018-04-06      3      5

我们可以使用Filter函数创建仅包含数字列的新数据集,然后获取这些列的名称。之后,我们将对字符列执行相同的操作。

numeric_data <- Filter(is.numeric, my_table)
numeric_columns <- names(numeric_data)
numeric_columns
# [1] "value1" "value2"

character_data <- Filter(is.character, my_table)
character_columns <- names(character_data)
character_columns
# [1] "name1" "name2"

如果您担心大数据效率低下,请不要这样做。这里没有任何数据实际被复制。

address(my_table$name1)
# [1] "0000000004601058"
address(character_data$name1)
# [1] "0000000004601058"

然后,我们会按date列的值汇总字符和数值。 j的{​​{1}}部分可以包含任何常规R代码,这些代码在每个副组内执行。 data.table变量是按组的子集.SD,因此我们可以使用它来抓取数字或字符列。

data.table