R:在一个步骤中聚合具有不同函数的数据表
我有一个数据表R:在一个步骤中聚合具有不同函数的数据表,r,data.table,aggregate,R,Data.table,Aggregate,我有一个数据表my_table,包含数字、字符和日期(POSIXct)列。现在我需要按日期聚合它,其中对于每个日期,数字列应按平均值聚合,字符和日期列应仅具有一个可用值(假设第一次出现)。我喜欢这样: name date value "test" 2018-04-04 1 "test" 2018-04-04 2 "test" 2018-04-05 8 "test" 2018-04-06 3
my_table
,包含数字、字符和日期(POSIXct
)列。现在我需要按日期聚合它,其中对于每个日期,数字列应按平均值聚合,字符和日期列应仅具有一个可用值(假设第一次出现)。我喜欢这样:
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
不是数字。我如何告诉函数只使用一个(或第一个,我不介意)出现的“test”
而不是NA
让事情变得更难一些:在我的实际情况中,实际上有很多列需要使用mean(如果它们是数字)或第一次出现(如果它们是character
或POSIXct
)进行聚合 方法1
使用聚合的基本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
表示df
中除值
以外的所有列
方法2
tidyverse
使用groupby
和summary
解决方案:
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
样本数据
df如果您实际上使用的是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
如果你担心这对大数据来说是低效的,不要。这里没有实际复制的数据
address(my_table$name1)
# [1] "0000000004601058"
address(character_data$name1)
# [1] "0000000004601058"
然后,我们将根据date
列的值汇总字符和数值。数据的j
部分。表
可以有任何常规的R代码,在每个分组内部执行。.SD
变量是by组作为data.table
的子集,因此我们可以使用它来获取数字或字符列
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"
my_table[
,
{
means <- lapply(
X = .SD[, numeric_columns, with = FALSE],
FUN = mean
)
firsts <- .SD[1, character_columns, with = FALSE]
append(firsts, means)
},
by = "date"
]
# date name1 name2 value1 value2
# 1: 2018-04-04 a W 1.5 6.5
# 2: 2018-04-05 c Y 8.0 2.0
# 3: 2018-04-06 d Z 3.0 5.0
my_表[
,
{
意思是您可以根据变量的类定义自己的摘要函数来执行您想要的操作
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
我真的很喜欢使用Base R的那一个,但是如果我不能命名所有的列,在这种情况下,date
和name
?如果我有60多个列,其中我不知道它们的确切数据类型和顺序怎么办?那么我就不能像value~date+name+col1+col2+…
那样列出它们。有什么办法吗?@s6hebern你呢可以使用value~。
,其中点
表示除value
之外的所有列聚合使用公式
方法非常通用。我编辑了我的答案以给出一个示例。这都是非常棒的东西(喜欢value~。
),但目前还不是我所需要的。编辑了这个问题,希望能让它更清楚一点。聚合做了它应该做的事情,我只需要去掉NA
s。我可以用NA.action
来解决这个问题吗?@s6hebern我看不到你的问题有任何变化。你可能忘记更新样本数据了吗?我建议你再做一次不要像你那样使用aggregate
;使用公式方法,你不会得到name
的NA
s。我基本上需要另一种方法,也许这是误导性的。我需要聚合除date
之外的所有列,因为这是聚合的基础。我想我就是不能用这种方法应该这样做,并且必须坚持@Renu的解决方案,但是您的示例让我对聚合有了深刻的了解,所以非常感谢这一点,因为它工作得很顺利,但是您必须首先执行库(lubridate)
我在is.POSIXct(x)中得到了错误消息error in is.POSIXct(x):找不到函数“is.POSIXct”
,所以我就这样做了,发现我必须使用lubridate
软件包。这很好,当然在我的现实世界中,使用函数的解决方案实际上是必要的。对于这个非常基本的示例,可能不是,但我有一大堆不同的列,我无法一直键入
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"
my_table[
,
{
means <- lapply(
X = .SD[, numeric_columns, with = FALSE],
FUN = mean
)
firsts <- .SD[1, character_columns, with = FALSE]
append(firsts, means)
},
by = "date"
]
# date name1 name2 value1 value2
# 1: 2018-04-04 a W 1.5 6.5
# 2: 2018-04-05 c Y 8.0 2.0
# 3: 2018-04-06 d Z 3.0 5.0
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]