R中不同子集与不同数据的乘法
Multiplication of different subsets with different data in R
我有一个很大的数据集,我把它分成了子集。对于每个子集,我必须使用不同的数字进行相同的计算。示例:
Main Table
x a b c d
A 1 2 4 5
A 4 5 1 7
A 3 5 6 2
B 4 5 2 9
B 3 5 2 8
C 4 2 5 2
C 1 9 6 9
C 1 2 3 4
C 6 3 6 2
Additional Table for A
a b c d
A 5 1 6 1
Additional Table for B
a b c d
B 1 5 2 6
Additional Table for C
a c c d
C 8 2 4 1
我需要将 Main Table 中的所有行 A 与 A 的 Additional Table 中的值相乘,Main table 中的所有 B 行与 B 中的值和主要 table 中所有 B 行的值都来自 C。将额外的 table 合并为一个组合行是完全没问题的,如果这样可以使解决方案更容易。
我考虑过 for 循环,但我无法将不同的乘法器(来自其他 Tables)放入代码中。由于存在大量子组,因此应避免手动对每个乘法进行编码。我该如何做这个乘法?
我们可以在split
主数据'df'后使用Map
(假设所有数据集都是data.frame
。
df[-1] <- unsplit(Map(function(x,y) x*y[col(x)],
split(df[-1], df$x),
list(unlist(dfA), unlist(dfB), unlist(dfC))), df$x)
df
# x a b c d
#1 A 5 2 24 5
#2 A 20 5 6 7
#3 A 15 5 36 2
#4 B 4 25 4 54
#5 B 3 25 4 48
#6 C 32 4 20 2
#7 C 8 18 24 9
#8 C 8 4 12 4
#9 C 48 6 24 2
或者我们可以使用更快的选项data.table
library(data.table)
setnames(setDT(do.call(rbind, list(dfA, dfB, dfC)), keep.rownames=TRUE)[df,
.(a= a*i.a, b= b*i.b, c = c*i.c, d= d*i.d), on = c('rn' = 'x'), by = .EACHI], 1, 'x')[]
# x a b c d
#1: A 5 2 24 5
#2: A 20 5 6 7
#3: A 15 5 36 2
#4: B 4 25 4 54
#5: B 3 25 4 48
#6: C 32 4 20 2
#7: C 8 18 24 9
#8: C 8 4 12 4
#9: C 48 6 24 2
如果有很多列,上面的操作会很困难,在这种情况下,我们可以使用 mget
来检索列并在 i.
列上执行 *
Map
setDT(do.call(rbind, list(dfA, dfB, dfC)), keep.rownames=TRUE)[df,
Map(`*`, mget(names(df)[-1]), mget(paste0("i.", names(df)[-1]))) ,
on = c('rn' = 'x'), by = .EACHI]
如果我们开始添加 table 作为 addDf
和主要 table 作为 df
:
addDf
x a b c d
A A 5 1 6 1
B B 1 5 2 6
C C 8 2 4 1
我们可以使用合并和矩阵的逐元素乘法,
df[-1] <- merge(addDf, data.frame(x = df[1]), by = "x")[-1] * df[order(df[1]), -1]
df
x a b c d
1 A 5 2 24 5
2 A 20 5 6 7
3 A 15 5 36 2
4 B 4 25 4 54
5 B 3 25 4 48
6 C 32 4 20 2
7 C 8 18 24 9
8 C 8 4 12 4
9 C 48 6 24 2
注意:从@akrun 借用了一些语法糖作为 df[-1]
赋值。
我有一个很大的数据集,我把它分成了子集。对于每个子集,我必须使用不同的数字进行相同的计算。示例:
Main Table
x a b c d
A 1 2 4 5
A 4 5 1 7
A 3 5 6 2
B 4 5 2 9
B 3 5 2 8
C 4 2 5 2
C 1 9 6 9
C 1 2 3 4
C 6 3 6 2
Additional Table for A
a b c d
A 5 1 6 1
Additional Table for B
a b c d
B 1 5 2 6
Additional Table for C
a c c d
C 8 2 4 1
我需要将 Main Table 中的所有行 A 与 A 的 Additional Table 中的值相乘,Main table 中的所有 B 行与 B 中的值和主要 table 中所有 B 行的值都来自 C。将额外的 table 合并为一个组合行是完全没问题的,如果这样可以使解决方案更容易。
我考虑过 for 循环,但我无法将不同的乘法器(来自其他 Tables)放入代码中。由于存在大量子组,因此应避免手动对每个乘法进行编码。我该如何做这个乘法?
我们可以在split
主数据'df'后使用Map
(假设所有数据集都是data.frame
。
df[-1] <- unsplit(Map(function(x,y) x*y[col(x)],
split(df[-1], df$x),
list(unlist(dfA), unlist(dfB), unlist(dfC))), df$x)
df
# x a b c d
#1 A 5 2 24 5
#2 A 20 5 6 7
#3 A 15 5 36 2
#4 B 4 25 4 54
#5 B 3 25 4 48
#6 C 32 4 20 2
#7 C 8 18 24 9
#8 C 8 4 12 4
#9 C 48 6 24 2
或者我们可以使用更快的选项data.table
library(data.table)
setnames(setDT(do.call(rbind, list(dfA, dfB, dfC)), keep.rownames=TRUE)[df,
.(a= a*i.a, b= b*i.b, c = c*i.c, d= d*i.d), on = c('rn' = 'x'), by = .EACHI], 1, 'x')[]
# x a b c d
#1: A 5 2 24 5
#2: A 20 5 6 7
#3: A 15 5 36 2
#4: B 4 25 4 54
#5: B 3 25 4 48
#6: C 32 4 20 2
#7: C 8 18 24 9
#8: C 8 4 12 4
#9: C 48 6 24 2
如果有很多列,上面的操作会很困难,在这种情况下,我们可以使用 mget
来检索列并在 i.
列上执行 *
Map
setDT(do.call(rbind, list(dfA, dfB, dfC)), keep.rownames=TRUE)[df,
Map(`*`, mget(names(df)[-1]), mget(paste0("i.", names(df)[-1]))) ,
on = c('rn' = 'x'), by = .EACHI]
如果我们开始添加 table 作为 addDf
和主要 table 作为 df
:
addDf
x a b c d
A A 5 1 6 1
B B 1 5 2 6
C C 8 2 4 1
我们可以使用合并和矩阵的逐元素乘法,
df[-1] <- merge(addDf, data.frame(x = df[1]), by = "x")[-1] * df[order(df[1]), -1]
df
x a b c d
1 A 5 2 24 5
2 A 20 5 6 7
3 A 15 5 36 2
4 B 4 25 4 54
5 B 3 25 4 48
6 C 32 4 20 2
7 C 8 18 24 9
8 C 8 4 12 4
9 C 48 6 24 2
注意:从@akrun 借用了一些语法糖作为 df[-1]
赋值。