数到 data.table 后完成所有组合
Complete with all combinations after counting on data.table
我的数据中有些列作为因子,有些列作为字符。我想计算所有组合并用 data.table 语法编写一个函数
# Load libraries
library(dplyr)
library(data.table)
# Create data
i_df = iris %>%
filter(Species != 'virginica') %>%
mutate(
len = ifelse(Sepal.Length > 6, 'large', 'tiny'),
width = ifelse(Sepal.Width > 3, 'thick', 'thin'),
color = ifelse(Species == 'setosa', 'green', 'red')
) %>%
mutate(
len = factor(len, levels = c('large', 'med_len', 'tiny')),
width = factor(width, levels = c('thick', 'med_width', 'thin'))
)
这将是我的函数的一个例子:
myfun = function(d, g, mode) {
# Convert to data.table
setDT(d)
# Counting
res = d[, .N, by = g]
# Complete combinations
setkeyv(res, cols = g)
res = switch(
mode,
manual = {
res[CJ(levels(d$Species), levels(d$len), levels(d$width), unique(d$color)),]
},
auto = {
m = res[, do.call(CJ, c(.SD, unique = TRUE)), .SDcols = g]
res[m, on = g]
}
)
# Add zero when NA
res[is.na(res)] = 0
# Return
return(res)
}
如何运行:
g_tmp = c('Species', 'len', 'width', 'color')
myfun(d = i_df, g = g_tmp, mode = 'manual')
myfun(d = i_df, g = g_tmp, mode = 'auto')
如您所见,我使用的是 setkeyv
而不是 setkey
,因为我需要使用字符向量 g
。但是当 CJ
完成后,我无法使用字符向量输入 mode = 'auto'
。在那里,指示所有因素的所有因素水平和所有字符列的所有当前颜色 unique
。如您所见,使用 mode = 'manual'
,返回 54 行,使用 mode = 'auto'
,不返回不存在的因子水平,结果为 16 行。
我找到了 and ,但是当我混合使用因子和字符列时我无法使用它
由于一些列是一些不存在水平的因素,unique
在这里不好,只针对字符列
这是解决您的问题的一种可能方法。请注意,data.table
上下文中的参数 with=FALSE
允许使用标准 data.frame
规则 select 列。在下面的示例中,我假设用于计算所有组合的列作为 character 向量传递给 myfun
。
请记住,数据集中的任何列都不应命名为 gcases。 .EACHI
in by
允许对 i
中的每一行执行一些操作。
myfun = function(d, g) {
# get levels (for factors) and unique values for other types.
fn <- function(x) if(is.factor(x)) levels(x) else unique(x)
gcases <- lapply(setDT(d, key=g)[, g, with=FALSE], fn)
# count based on all combinations
d[do.call(CJ, gcases), .N, keyby=.EACHI]
}
我的数据中有些列作为因子,有些列作为字符。我想计算所有组合并用 data.table 语法编写一个函数
# Load libraries
library(dplyr)
library(data.table)
# Create data
i_df = iris %>%
filter(Species != 'virginica') %>%
mutate(
len = ifelse(Sepal.Length > 6, 'large', 'tiny'),
width = ifelse(Sepal.Width > 3, 'thick', 'thin'),
color = ifelse(Species == 'setosa', 'green', 'red')
) %>%
mutate(
len = factor(len, levels = c('large', 'med_len', 'tiny')),
width = factor(width, levels = c('thick', 'med_width', 'thin'))
)
这将是我的函数的一个例子:
myfun = function(d, g, mode) {
# Convert to data.table
setDT(d)
# Counting
res = d[, .N, by = g]
# Complete combinations
setkeyv(res, cols = g)
res = switch(
mode,
manual = {
res[CJ(levels(d$Species), levels(d$len), levels(d$width), unique(d$color)),]
},
auto = {
m = res[, do.call(CJ, c(.SD, unique = TRUE)), .SDcols = g]
res[m, on = g]
}
)
# Add zero when NA
res[is.na(res)] = 0
# Return
return(res)
}
如何运行:
g_tmp = c('Species', 'len', 'width', 'color')
myfun(d = i_df, g = g_tmp, mode = 'manual')
myfun(d = i_df, g = g_tmp, mode = 'auto')
如您所见,我使用的是 setkeyv
而不是 setkey
,因为我需要使用字符向量 g
。但是当 CJ
完成后,我无法使用字符向量输入 mode = 'auto'
。在那里,指示所有因素的所有因素水平和所有字符列的所有当前颜色 unique
。如您所见,使用 mode = 'manual'
,返回 54 行,使用 mode = 'auto'
,不返回不存在的因子水平,结果为 16 行。
我找到了
由于一些列是一些不存在水平的因素,unique
在这里不好,只针对字符列
这是解决您的问题的一种可能方法。请注意,data.table
上下文中的参数 with=FALSE
允许使用标准 data.frame
规则 select 列。在下面的示例中,我假设用于计算所有组合的列作为 character 向量传递给 myfun
。
请记住,数据集中的任何列都不应命名为 gcases。 .EACHI
in by
允许对 i
中的每一行执行一些操作。
myfun = function(d, g) {
# get levels (for factors) and unique values for other types.
fn <- function(x) if(is.factor(x)) levels(x) else unique(x)
gcases <- lapply(setDT(d, key=g)[, g, with=FALSE], fn)
# count based on all combinations
d[do.call(CJ, gcases), .N, keyby=.EACHI]
}