如何对 data.table 的每一行应用不同的多参数函数?
How to apply a different multi-argument function to each row of a data.table?
我有一个 data.table 以下示例格式。
dt <- data.table(l = c("apple","ball","cat"),
m = c(1,2,3),
n = c("I ate apple", "I played ball", "cat ate pudding"))
我想将 sub
应用于每一行的列 (n
),其模式来自另一列 (l
)。我该怎么做?
我正在寻找的输出是,
l m n o
1: apple 1 I ate apple I ate
2: ball 2 I played ball I played
3: cat 3 cat ate pudding ate pudding
我已经尝试在 data.table 中使用方法 mapply(do.call, list(sub), ...)
和赋值运算符,但是 sub
(模式、替换、字符串)的参数需要是一个嵌套列表do.call
我一直在思考如何正确地编写它。
所以我们想做一个按行计算,return它定义为一个新列o
mapply
绝对是正确的函数族,但是 mapply
(和 sapply
)会在 return 之前简化列表的输出。 data.table
喜欢列表。 Map
只是 mapply(..., simplify = FALSE)
的表达快捷方式,它不会修改 return.
下面是我们要计算的结果,但还是不太对。 (data.table
将 list-output 解释为单独的列)
> dt[, Map(sub, l, '', n)]
apple ball cat
1: I ate I played ate pudding
所以我们想更进一步,将它包装在一个列表中以获得我们想要的输出:
>dt[, .(Map(sub, l, '', n))]
V1
1: I ate
2: I played
3: ate pudding
现在我们可以使用 :=
分配它
> dt[, o := Map(sub, l, '', n)]
> dt
l m n o
1: apple 1 I ate apple I ate
2: ball 2 I played ball I played
3: cat 3 cat ate pudding ate pudding
编辑:正如所指出的,这导致 o
成为 list-column。
我们可以通过使用标准 mapply
来避免这种情况,尽管我更喜欢 Map
的 one-size-fits-all 方法(每一行创建一个输出,它进入一个列表。不管输出结果如何,这总是有效的,然后我们可以在最后 type-convert。)
dt[, o := mapply(sub, l, '', n)]
我们可以通过 paste
ing 'l' 的内容来实现向量化方法,将其用作 sub
中的 pattern
参数来删除子字符串并创建新的列 'o'
dt[, o := trimws(sub(paste(l, collapse="|"), "", n))]
dt
# l m n o
#1: apple 1 I ate apple I ate
#2: ball 2 I played ball I played
#3: cat 3 cat ate pudding ate pudding
我有一个 data.table 以下示例格式。
dt <- data.table(l = c("apple","ball","cat"),
m = c(1,2,3),
n = c("I ate apple", "I played ball", "cat ate pudding"))
我想将 sub
应用于每一行的列 (n
),其模式来自另一列 (l
)。我该怎么做?
我正在寻找的输出是,
l m n o
1: apple 1 I ate apple I ate
2: ball 2 I played ball I played
3: cat 3 cat ate pudding ate pudding
我已经尝试在 data.table 中使用方法 mapply(do.call, list(sub), ...)
和赋值运算符,但是 sub
(模式、替换、字符串)的参数需要是一个嵌套列表do.call
我一直在思考如何正确地编写它。
所以我们想做一个按行计算,return它定义为一个新列o
mapply
绝对是正确的函数族,但是 mapply
(和 sapply
)会在 return 之前简化列表的输出。 data.table
喜欢列表。 Map
只是 mapply(..., simplify = FALSE)
的表达快捷方式,它不会修改 return.
下面是我们要计算的结果,但还是不太对。 (data.table
将 list-output 解释为单独的列)
> dt[, Map(sub, l, '', n)]
apple ball cat
1: I ate I played ate pudding
所以我们想更进一步,将它包装在一个列表中以获得我们想要的输出:
>dt[, .(Map(sub, l, '', n))]
V1
1: I ate
2: I played
3: ate pudding
现在我们可以使用 :=
> dt[, o := Map(sub, l, '', n)]
> dt
l m n o
1: apple 1 I ate apple I ate
2: ball 2 I played ball I played
3: cat 3 cat ate pudding ate pudding
编辑:正如所指出的,这导致 o
成为 list-column。
我们可以通过使用标准 mapply
来避免这种情况,尽管我更喜欢 Map
的 one-size-fits-all 方法(每一行创建一个输出,它进入一个列表。不管输出结果如何,这总是有效的,然后我们可以在最后 type-convert。)
dt[, o := mapply(sub, l, '', n)]
我们可以通过 paste
ing 'l' 的内容来实现向量化方法,将其用作 sub
中的 pattern
参数来删除子字符串并创建新的列 'o'
dt[, o := trimws(sub(paste(l, collapse="|"), "", n))]
dt
# l m n o
#1: apple 1 I ate apple I ate
#2: ball 2 I played ball I played
#3: cat 3 cat ate pudding ate pudding