【问题标题】:Combining two dataframes to calculate variable when column names are equal to row values当列名等于行值时,结合两个数据框来计算变量
【发布时间】:2019-05-18 03:39:59
【问题描述】:

我有两个数据框:一个数据框具有表示是否存在字符串匹配的二分变量,第二个数据框在不同维度上为该字符串应用“权重”。

例如,df1 可能如下所示:

organic    gluten_free    kosher   sugar_free
1          0              0        0
1          1              0        1
1          1              0        1
0          0              1        0
1          0              1        0

第二个数据框 (df2) 中的 行值 应与 df1列名 的值匹配,并且每一行中的值代表一个重量。

attribute    eco-friendly     healthy 
organic      2                3         
gluten_free  1                4         
kosher       3                3         
sugar_free   2                3         

然后,当df1 中的colname 等于df2 中的行值时,我想计算df1 中每个行值的权重乘积到单独的索引中。为了清楚起见,我在下面包含了eco-friendly 索引的具体计算:

organic    gluten_free    kosher   sugar-free  eco-friendly
1          0              0        0           (1*2 + 0*1 + 0*3 + 0*2)
1          1              0        1           (1*2 + 1*1 + 0*3 + 1*2)
1          1              0        1           (1*2 + 1*1 + 0*3 + 1*2)
0          0              1        0           (0*2 + 0*1 + 1*3 + 0*2)
1          0              1        0           (1*2 + 0*1 + 1*3 + 0*2)

我编写了一个非常丑陋且缓慢的循环函数来完成这项任务,但我相信存在一个更优雅的解决方案。下面是一些额外的示例数据。

> dput(df1[1:100,]) 
structure(list(organic = c("0", "0", "0", "0", "0", "0", "1",  "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",  "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",  "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "0", "0", "0",  "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",  "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",  "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",  "0", "0"), gluten_free = c("0", "1", "0", "0", "1", "0", "0",  "0", "0", "0", "0", "0", "1", "0", "0", "1", "1", "1", "1", "1",  "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "0",  "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",  "0", "0", "0", "0", "1", "1", "0", "1", "1", "1", "1", "1", "1",  "0", "0", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0",  "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0",  "0", "0", "0", "0", "1", "1", "0", "0", "0", "0", "0", "1", "0",  "1", "0"), kosher = c("0", "0", "0", "0", "0", "0", "0", "0",  "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", "0", "0", "1",  "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",  "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",  "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",  "1", "1", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",  "1", "0", "1", "1", "1", "0", "1", "1", "0", "1", "1", "1", "1",  "1", "1", "1", "0", "0", "1", "1", "0", "0", "1", "0", "0", "0",  "1")), row.names = c("2", "3", "4", "5", "6", "7", "8", "9",  "10", "11", "12", "15", "17", "18", "19", "22", "23", "24", "25",  "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36",  "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47",  "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58",  "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",  "70", "71", "72", "73", "74", "77", "78", "79", "80", "81", "83",  "84", "85", "86", "87", "88", "91", "92", "93", "95", "97", "98",  "101", "103", "105", "106", "108", "117", "124", "125", "127",  "129", "131", "132", "133", "136", "137"), class = "data.frame")

> dput(df2[1:3,]) 
structure(list(attribute = c("organic", "gluten_free", "kosher"), eco_friendly = c(1L, 3L, 2L), healthy = c(2L, 0L, 1L)), row.names = 1:3, class = "data.frame")

【问题讨论】:

    标签: r


    【解决方案1】:

    这是你想要的吗?

    df <- data.frame(organic = c(1, 1, 1, 0, 1), gluten_free = c(0, 1, 1, 0, 0),           
                     kosher = c(0, 0, 0, 1, 1), sugar_free = c(0, 1, 1, 0, 0))
    df %>% mutate(eco_friendly = organic * 2 + gluten_free * 1 + kosher * 3 + sugar_free * 2)
    

    【讨论】:

    • 这不只是硬编码OP给出的公式吗?我认为他们想要一个动态解决方案,而不需要说明索引的每个位置
    • 好的,知道了。不应该那么明显:O
    【解决方案2】:

    我们可以取两个dfs 的点积,记住%*% 运算符仅适用于数字矩阵:

    df1[] <- lapply(df1, as.numeric)
    output <- cbind(df1, as.matrix(df1) %*% as.matrix(df2[,-1]))
    

    这样做的缺点是df1 中的列和df2 中的行必须按正确的顺序排列。为了确保列和行顺序匹配,我们可以使用以下代码代替df2[,-1]

    df2[match(names(df1), df2$attribute),-1]

    输出:

    > head(output)
      organic gluten_free kosher eco_friendly healthy
    2       0           0      0            0       0
    3       0           1      0            3       0
    4       0           0      0            0       0
    5       0           0      0            0       0
    6       0           1      0            3       0
    7       0           0      0            0       0
    

    【讨论】:

    • 为了避免出错的可能性,添加类似df1&lt;-df1[ , order(names(df1))]df2 &lt;- df2[order(df2$attribute),] 以确保代码正常运行是否有意义?
    • @roody 是的,这是一种安全的方法。
    • 另一个关于相关扩展的问题:有没有一种有效的方法可以将df1 中的索引分数标准化为该函数中df2 中列的最大可能权重总和?我最初的想法是除以colSums(pr[,-1]),但要确保这是正确的。
    • @roody 或者你可以做df2[match(names(df1), df2$attribute),]
    • @roody 你将不得不通过一个例子来说明你的意思。例如,您必须解释“归一化”和“最大可能的权重总和”是什么意思
    猜你喜欢
    • 1970-01-01
    • 2022-01-10
    • 2016-05-18
    • 2018-12-20
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    相关资源
    最近更新 更多