r 如何将 mapply 与数据一起使用 table
r how to use mapply with a data table
我想做一个看似简单的 mapply 在数据中的应用 table。我想将一系列数据 table 列乘以另一列中的值。这是我的功能。 y 是将其他列中的值乘以的单列。 xIn 是要执行此操作的列名。
f.xRatio <- function(xIn, y) {return(y * (xIn + 1)/(xIn - 1))}
我有一个数据 table,其中有一个名为 GDPratio 的列和一些名称如下的列
x.food1、x.food2 等。我将这些列名称放入一个名为 x 的变量中
x <- paste0("x.", foodNames)
我用函数创建的新列的名称创建了另一个变量
xRatio <- paste0("xRatio.", foodNames)
这是我尝试使用 mapply 从函数创建 xRatio 列的两个版本。
dt[, (xRatio) := mapply(FUN = f.xRatio, xIn = .SD, y = GDPRatio), .SDcols = (x)]
dt[, (xRatio) := mapply(FUN = f.xRatio, xIn = .(x), y = GDPRatio)]
都不行。我认为第一个很接近。我希望有人可以指出我逻辑中的缺陷,而无需我创建可重现的示例。
如果我们使用 Map/mapply
,请确保将单列 'GDPRatio' 括在 list
中,以将其作为在 list
中回收的单个单元.SD
中的列。
dt[, (xRatio) := Map(f.xRatio, .SD, list(GDPRatio)), .SDcols = x]
否则,该单元将是 vector
中的单个元素,并与 .SD
的相应列一起回收,并导致 length
问题,如 OP 代码中所述
dt[, (xRatio) := Map(f.xRatio, .SD, GDPRatio), .SDcols = x]
Warning messages: 1: In mapply(FUN = f, ..., SIMPLIFY = FALSE) :
longer argument not a multiple of length of shorter 2: In
[.data.table
(dt, , :=
((xRatio), Map(f.xRatio, .SD, GDPRatio)), :
Supplied 2 columns to be assigned a list (length 5) of values (3
unused)
数据
foodNames <- c("food1", "food2")
x <- paste0("x.", foodNames)
xRatio <- paste0("xRatio.", foodNames)
set.seed(24)
dt <- data.table(x.food1 = 2:6, x.food2 = 6:10, val = rnorm(5),
GDPRatio = c(0.5, 0.2, 0.3, 0.4, 0.1))
考虑不应用循环和运行跨列子集的矢量化算法:
dt[, xRatio] <- dt$GDPRatio * (dt[, foodNames, with=FALSE] + 1) /
(dt[, foodNames, with=FALSE] - 1)
这等同于@Frank 的建议和@ak运行 使用以下随机数据的回答:
foodNames <- c("apple", "banana", "orange")
set.seed(4252018) # SEEDED FOR REPRODUCIBILITY
dt <- data.table(
apple = abs(rnorm(50)) * 100,
banana = abs(rnorm(50)) * 100,
orange = abs(rnorm(50)) * 100,
GDPRatio = abs(rnorm(50))
)
f.xRatio <- function(xIn, y) {return(y * (xIn + 1)/(xIn - 1))}
xRatio <- paste0("xRatio.", foodNames)
# @Parfait's NO LOOP FUNCTION
dt[, xRatio] <- dt$GDPRatio * (dt[, foodNames, with=FALSE] + 1) /
(dt[, foodNames, with=FALSE] - 1)
# @Frank's COMMENT
frank_dt <- dt[, (xRatio) := lapply(.SD, f.xRatio, y = GDPRatio), .SDcols = xRatio]
all.equal(dt, frank_dt)
# [1] TRUE
identical(dt, newdt)
# [1] TRUE
# @akrun'S ANSWER
akrun_dt <- dt[, (xRatio) := Map(f.xRatio, .SD, list(GDPRatio)), .SDcols = xRatio]
all.equal(dt, akrun_dt)
# [1] TRUE
identical(dt, akrun_dt)
# [1] TRUE
我想做一个看似简单的 mapply 在数据中的应用 table。我想将一系列数据 table 列乘以另一列中的值。这是我的功能。 y 是将其他列中的值乘以的单列。 xIn 是要执行此操作的列名。
f.xRatio <- function(xIn, y) {return(y * (xIn + 1)/(xIn - 1))}
我有一个数据 table,其中有一个名为 GDPratio 的列和一些名称如下的列 x.food1、x.food2 等。我将这些列名称放入一个名为 x 的变量中
x <- paste0("x.", foodNames)
我用函数创建的新列的名称创建了另一个变量
xRatio <- paste0("xRatio.", foodNames)
这是我尝试使用 mapply 从函数创建 xRatio 列的两个版本。
dt[, (xRatio) := mapply(FUN = f.xRatio, xIn = .SD, y = GDPRatio), .SDcols = (x)]
dt[, (xRatio) := mapply(FUN = f.xRatio, xIn = .(x), y = GDPRatio)]
都不行。我认为第一个很接近。我希望有人可以指出我逻辑中的缺陷,而无需我创建可重现的示例。
如果我们使用 Map/mapply
,请确保将单列 'GDPRatio' 括在 list
中,以将其作为在 list
中回收的单个单元.SD
中的列。
dt[, (xRatio) := Map(f.xRatio, .SD, list(GDPRatio)), .SDcols = x]
否则,该单元将是 vector
中的单个元素,并与 .SD
的相应列一起回收,并导致 length
问题,如 OP 代码中所述
dt[, (xRatio) := Map(f.xRatio, .SD, GDPRatio), .SDcols = x]
Warning messages: 1: In mapply(FUN = f, ..., SIMPLIFY = FALSE) :
longer argument not a multiple of length of shorter 2: In[.data.table
(dt, ,:=
((xRatio), Map(f.xRatio, .SD, GDPRatio)), : Supplied 2 columns to be assigned a list (length 5) of values (3 unused)
数据
foodNames <- c("food1", "food2")
x <- paste0("x.", foodNames)
xRatio <- paste0("xRatio.", foodNames)
set.seed(24)
dt <- data.table(x.food1 = 2:6, x.food2 = 6:10, val = rnorm(5),
GDPRatio = c(0.5, 0.2, 0.3, 0.4, 0.1))
考虑不应用循环和运行跨列子集的矢量化算法:
dt[, xRatio] <- dt$GDPRatio * (dt[, foodNames, with=FALSE] + 1) /
(dt[, foodNames, with=FALSE] - 1)
这等同于@Frank 的建议和@ak运行 使用以下随机数据的回答:
foodNames <- c("apple", "banana", "orange")
set.seed(4252018) # SEEDED FOR REPRODUCIBILITY
dt <- data.table(
apple = abs(rnorm(50)) * 100,
banana = abs(rnorm(50)) * 100,
orange = abs(rnorm(50)) * 100,
GDPRatio = abs(rnorm(50))
)
f.xRatio <- function(xIn, y) {return(y * (xIn + 1)/(xIn - 1))}
xRatio <- paste0("xRatio.", foodNames)
# @Parfait's NO LOOP FUNCTION
dt[, xRatio] <- dt$GDPRatio * (dt[, foodNames, with=FALSE] + 1) /
(dt[, foodNames, with=FALSE] - 1)
# @Frank's COMMENT
frank_dt <- dt[, (xRatio) := lapply(.SD, f.xRatio, y = GDPRatio), .SDcols = xRatio]
all.equal(dt, frank_dt)
# [1] TRUE
identical(dt, newdt)
# [1] TRUE
# @akrun'S ANSWER
akrun_dt <- dt[, (xRatio) := Map(f.xRatio, .SD, list(GDPRatio)), .SDcols = xRatio]
all.equal(dt, akrun_dt)
# [1] TRUE
identical(dt, akrun_dt)
# [1] TRUE