对于给定的数据帧,我想将数组的值乘以数据帧的列。数据框由行组成,包含名称,数值和两个因子值:
name credit gender group
n1 10 m A
n2 20 f B
n3 30 m A
n4 40 m B
n5 50 f C
可以使用以下命令生成此数据框:
name <- c('n1','n2','n3','n4','n5')
credit <- c(10,20,30,40,50)
gender <- c('m','f','m','m','f')
group <- c('A','B','A','B','C')
DF <-data.frame(cbind(name,credit,gender,group))
# binds columns together and uses it as a data frame
此外,我们有一个从数据框派生的矩阵(在更复杂的情况下,这将是一个数组)。该矩阵包含属于特定类别的所有合约的总和值(以m / f和A / B / C为特征):
m f
A 40 NA
B 40 20
C NA 50
目标是通过使用分配给矩阵中每个类别的相应值,将DF $信用值中的值相乘,例如: DF中第一行的值10将乘以40(由m和A定义的类别)。
结果如下:
name credit gender group result
n1 10 m A 400
n2 20 f B 400
n3 30 m A 1200
n4 40 m B 1600
n5 50 f C 2500
如果可能的话,我想使用R base软件包执行此操作,但我愿意为任何有用的解决方案做好准备。
答案 0 :(得分:3)
您可以通过从derived
和DF$group
中创建索引矩阵,将一组索引构建到DF$gender
(作为派生矩阵)。 as.character
存在的原因是因为DF$group
和DF$gender
是因素,而我只想要字符索引。
>idx = matrix( c(as.character(DF$group),as.character(DF$gender)),ncol=2)
>idx
[,1] [,2]
[1,] "A" "m"
[2,] "B" "f"
[3,] "A" "m"
[4,] "B" "m"
[5,] "C" "f"
>DF$result = DF$credit * derived[idx]
请注意最后一行,使用上面的代码生成DF
,您的数字列将作为因素(即DF$credit
是一个因素)。在这种情况下,您需要执行as.numeric(DF$credit)*derived[idx]
。但是,我想在您的实际数据中,您的数据框没有DF$credit
作为因素,而是数字。
答案 1 :(得分:2)
当你创建data.frame对象时,不要使用cbind,它不是必需的,它会强制信用变量成为一个因素。
只需使用DF <- data.frame(name, credit, gender, group)
然后运行一个遍历data.frame对象中每一行的for循环。
n <- length(DF$credit)
result <- rep(0, n)
for(i in 1:n) {
result[i] <- DF$credit[i] * sum(DF$credit[DF$gender==DF$gender[i] & DF$group==DF$group[i]])
}
将data.frame对象替换为包含结果的新对象。
DF <- data.frame(name, credit, gender, group, result)
答案 2 :(得分:2)
我推荐使用plyr
软件包,但您可以使用基本的by
函数执行此操作:
> by(DF, DF['name'], function (row) row$credit * m[as.character(row$group), as.character(row$gender)])
name: n1
[1] 400
---------------------------------------------------------------------
name: n2
[1] 400
---------------------------------------------------------------------
name: n3
[1] 1200
---------------------------------------------------------------------
name: n4
[1] 1600
---------------------------------------------------------------------
name: n5
[1] 2500
plyr
可以将结果作为一个很好的数据框:
> ddply(DF, .(name), function (row) row$credit * m[as.character(row$group), as.character(row$gender)])
name V1
1 n1 400
2 n2 400
3 n3 1200
4 n4 1600
5 n5 2500