【问题标题】:Use array result as multiplier for the original data frame使用数组结果作为原始数据帧的乘数
【发布时间】:2011-12-20 23:52:07
【问题描述】:

对于给定的数据框,我想将数组的值乘以数据框的一列。数据框由行组成,包含名称、数值和两个因子值:

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$credit 中的值,例如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 基础包来执行此操作,但我愿意接受任何有效的有用解决方案。

【问题讨论】:

    标签: arrays r matrix dataframe r-factor


    【解决方案1】:

    您可以通过在DF$groupDF$gender 中创建一个索引矩阵,将一组索引构造到derived(作为您的派生矩阵)中。 as.character 存在的原因是因为 DF$groupDF$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 用于矩阵查找。但是……如果他在使用 data.frame 之前使用了cbind,那么一切都是“字符”,而默认设置中的data.frame 将这一切都变成了因素。所以需要有as.numeric(as.character(...)) 处理才能得到正确的结果。
    • 感谢您的贡献。我知道 as.numeric(...) 必须应用于 DF$credit。例如,您的答案非常有效。我将尝试测试派生对象是否为数组的更复杂的情况。
    【解决方案2】:

    当你创建 data.frame 对象时,不要使用 cbind,这不是必须的,它会强制 credit 变量成为一个因素。

    只需使用DF &lt;- data.frame(name, credit, gender, group)

    然后运行一个 for 循环,遍历 data.frame 对象中的每一行。

    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)
    

    【讨论】:

    • 不是cbind 强制转换为一个因素。它强制进入“字符”模式。 data.frame 函数的默认值为 stringsAsFactors=TRUE,它会将所有字符向量强制转换为因子。
    • 这是第三种方法,也可以在示例数据上产生正确的结果。感谢您的贡献!
    【解决方案3】:

    我推荐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
    

    【讨论】:

    • +1 plyr,我会推荐它,但对于 OP 更喜欢 base R.ddply 太棒了!
    • 亲爱的丹尼尔,谢谢你的榜样。我尝试了生成列表的 by 函数。假设“m”代表派生矩阵,我可以让它工作(稍微描述一下你的代码在做什么会让它更容易理解)。当我有更多时间时,我也会研究 plyr 包。
    猜你喜欢
    • 1970-01-01
    • 2014-10-05
    • 1970-01-01
    • 2018-08-03
    • 2017-05-04
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    相关资源
    最近更新 更多