使用 data.table 和用于多列的 for 循环创建表
Create tables by using data.table and a for loop for multiple columns
我需要使用 data.table 来加速代码。我被困在如何引用从向量索引的变量上。
数据:
df <- data.frame(
id=c(1,1,1,2,2,2,3,3,3),
year=as.character(c(2014, 2015, 2016, 2015, 2015, 2016, NA, NA, 2016)),
code=c(1,2,2, 1,2,3, 3,4,5),
dv1=1:9,
dv2=2:10
) %>% as.data.table()
dtplyr 代码:
cols <- c("dv1", "dv2")
test <- function(data, columns, group) {
for(i in seq_along(columns)) {
sub1 <- df %>%
select("id", columns[i], group) %>%
group_by(.data[[group]]) %>%
summarise(mean=mean(.data[[columns[i]]], na.rm=T), sd=sd(.data[[columns[i]]], na.rm=T)) %>%
ungroup() %>%
as_tibble()
print(sub1)
}
}
data.table 尝试:
test <- function(data, columns, group) {
for(i in seq_along(columns)) {
sub1 <- df %>%
.[, .(id, columns[i], group)] %>%
.[, .(mean(.data[[columns[i]]], na.rm=T), sd=sd(.data[[columns[i]]], na.rm=T)), by=.data[[group]]] %>%
as_tibble()
print(sub1)
}
}
test(data=df, columns=cols, group="year")
这适用于单个变量:
df %>%
.[, .(id, dv1, year)] %>%
.[, .(mean(dv1, na.rm=T), sd=sd(dv1, na.rm=T)), by=year] %>%
as_tibble()
这可能需要一个相当不直观的 as.list/unlist 构造:
df <- data.frame(
id=c(1,1,1,2,2,2,3,3,3),
year=as.character(c(2014, 2015, 2016, 2015, 2015, 2016, NA, NA, 2016)),
code=c(1,2,2, 1,2,3, 3,4,5),
dv1=1:9,
dv2=2:10
) %>% as.data.table()
summary.func <- function(x) {
list( mean=mean(x), sd=sd(x) )
}
df[, as.list(unlist(lapply(.SD, summary.func))), by=group, .SDcols=cols ]
它产生:
year dv1.mean dv1.sd dv2.mean dv2.sd
1: 2014 1.000000 NA 2.000000 NA
2: 2015 3.666667 1.5275252 4.666667 1.5275252
3: 2016 6.000000 3.0000000 7.000000 3.0000000
4: <NA> 7.500000 0.7071068 8.500000 0.7071068
.data
未在 data.table
中使用
- 你在这里不需要
select
,这就是为什么你在 data.table
版本中也不需要 .[, .(id, columns[i], group)]
。
- 您可以使用
get
根据字符串获取列值。
因为这只是一个示例,所以我没有尝试简化循环以便您稍后可以在其中添加更复杂的东西。
library(data.table)
cols <- c("dv1", "dv2")
test <- function(data, columns, group) {
for(i in columns) {
sub1 <-df[, .(mean(get(i), na.rm=T), sd=sd(get(i), na.rm=T)), by=year]
print(sub1)
}
}
test(data=df, columns=cols, group="year")
# year V1 sd
#1: 2014 1.00 NA
#2: 2015 3.67 1.528
#3: 2016 6.00 3.000
#4: <NA> 7.50 0.707
# year V1 sd
#1: 2014 2.00 NA
#2: 2015 4.67 1.528
#3: 2016 7.00 3.000
#4: <NA> 8.50 0.707
我需要使用 data.table 来加速代码。我被困在如何引用从向量索引的变量上。
数据:
df <- data.frame(
id=c(1,1,1,2,2,2,3,3,3),
year=as.character(c(2014, 2015, 2016, 2015, 2015, 2016, NA, NA, 2016)),
code=c(1,2,2, 1,2,3, 3,4,5),
dv1=1:9,
dv2=2:10
) %>% as.data.table()
dtplyr 代码:
cols <- c("dv1", "dv2")
test <- function(data, columns, group) {
for(i in seq_along(columns)) {
sub1 <- df %>%
select("id", columns[i], group) %>%
group_by(.data[[group]]) %>%
summarise(mean=mean(.data[[columns[i]]], na.rm=T), sd=sd(.data[[columns[i]]], na.rm=T)) %>%
ungroup() %>%
as_tibble()
print(sub1)
}
}
data.table 尝试:
test <- function(data, columns, group) {
for(i in seq_along(columns)) {
sub1 <- df %>%
.[, .(id, columns[i], group)] %>%
.[, .(mean(.data[[columns[i]]], na.rm=T), sd=sd(.data[[columns[i]]], na.rm=T)), by=.data[[group]]] %>%
as_tibble()
print(sub1)
}
}
test(data=df, columns=cols, group="year")
这适用于单个变量:
df %>%
.[, .(id, dv1, year)] %>%
.[, .(mean(dv1, na.rm=T), sd=sd(dv1, na.rm=T)), by=year] %>%
as_tibble()
这可能需要一个相当不直观的 as.list/unlist 构造:
df <- data.frame(
id=c(1,1,1,2,2,2,3,3,3),
year=as.character(c(2014, 2015, 2016, 2015, 2015, 2016, NA, NA, 2016)),
code=c(1,2,2, 1,2,3, 3,4,5),
dv1=1:9,
dv2=2:10
) %>% as.data.table()
summary.func <- function(x) {
list( mean=mean(x), sd=sd(x) )
}
df[, as.list(unlist(lapply(.SD, summary.func))), by=group, .SDcols=cols ]
它产生:
year dv1.mean dv1.sd dv2.mean dv2.sd
1: 2014 1.000000 NA 2.000000 NA
2: 2015 3.666667 1.5275252 4.666667 1.5275252
3: 2016 6.000000 3.0000000 7.000000 3.0000000
4: <NA> 7.500000 0.7071068 8.500000 0.7071068
.data
未在data.table
中使用
- 你在这里不需要
select
,这就是为什么你在data.table
版本中也不需要.[, .(id, columns[i], group)]
。 - 您可以使用
get
根据字符串获取列值。
因为这只是一个示例,所以我没有尝试简化循环以便您稍后可以在其中添加更复杂的东西。
library(data.table)
cols <- c("dv1", "dv2")
test <- function(data, columns, group) {
for(i in columns) {
sub1 <-df[, .(mean(get(i), na.rm=T), sd=sd(get(i), na.rm=T)), by=year]
print(sub1)
}
}
test(data=df, columns=cols, group="year")
# year V1 sd
#1: 2014 1.00 NA
#2: 2015 3.67 1.528
#3: 2016 6.00 3.000
#4: <NA> 7.50 0.707
# year V1 sd
#1: 2014 2.00 NA
#2: 2015 4.67 1.528
#3: 2016 7.00 3.000
#4: <NA> 8.50 0.707