【问题标题】:R: converting fractions into decimals in a data frameR:将分数转换为数据框中的小数
【发布时间】:2018-02-23 20:14:04
【问题描述】:

我正在尝试将存储为分数形式的字符的数字数据帧转换为以十进制形式存储的数字。 (还有一些整数,也存储为 char。)我想保留数据框的当前结构,即我不想要一个列表作为结果。

示例数据框(注意:真实数据框将所有元素都作为字符,这是一个因素,但我不知道如何复制带有字符的数据框):

    a <- c("1","1/2","2")
    b <- c("5/2","3","7/2")
    c <- c("4","9/2","5")
    df <- data.frame(a,b,c)

我试过df[] &lt;- apply(df,1, function(x) eval(parse(text=x)))。这会正确计算数字,但仅适用于最后一列,并用它填充数据框。

结果:

   a  b    c
1  4  4.5  5
2  4  4.5  5
3  4  4.5  5

我也试过df[] &lt;- lapply(df, function(x) eval(parse(text=x))),结果如下(我也不知道为什么):

   a  b  c
1  3  3  2
2  3  3  2
3  3  3  2

想要的结果:

   a   b    c
1  1   2.5  4
2  0.5 3    4.5
3  2   3.5  5

非常感谢!

【问题讨论】:

    标签: r dataframe apply lapply fractions


    【解决方案1】:

    您可能正在寻找:

    df[] <- apply(df, c(1, 2), function(x) eval(parse(text = x)))
    df
        a   b   c
    1 1.0 2.5 4.0
    2 0.5 3.0 4.5
    3 2.0 3.5 5.0
    
    eval(parse(text = x))
    

    一次评估一个表达式,因此您需要逐个单元格地运行。

    编辑:如果无法评估某些数据框元素,您可以通过在函数内添加 ifelse 语句来解决此问题:

    df[] <- apply(df, c(1, 2), function(x) if(x %in% skip){NA} else {eval(parse(text = x))}) 
    

    其中skip是一个不应该被评估的元素向量。

    【讨论】:

    • 是的,这是一个错字,已经删除了评论。为混乱感到抱歉。您的解决方案在示例 df 上效果很好,不幸的是,这两种解决方案都不适用于我的真实数据。我最终得到了第一列中正确的小数,在行中反复粘贴在侧面。
    • 我正要这样做,但是当我把它剪下来时,我意识到最后有一个空列。删除它后,您的代码会神奇地运行。非常感谢您的帮助
    • 除了我删除的空列之外,有时还会出现随机的空单元格 (""),它们似乎会弄乱函数的结果。当数据框中有这样的单元格时,您能否帮助如何修改功能以使其仍然有效?谢谢
    • 您可以添加一个if else 语句,如:function(x) if(x %in% dont_eval) {NA} else {eval(parse(text = x)))} 并定义一个包含c(NA_character_, "")dont_eval 变量以及任何与您的功能混淆的东西。如果您可以提供具有问题值的新示例数据框,我可以将其添加到我的帖子中。
    • 谢谢!! df[] &lt;- apply(df, c(1, 2), function(x) if(x=="") {NA} else {eval(parse(text = x))}) 非常适合作为最终解决方案。我仍然只学习编码,因此非常感谢您的帮助
    【解决方案2】:
    1. 首先,你应该防止你的角色变成data.frame()中的因素

      df

      然后你可以在你的lapply 中包装一个简单的sapply/lapply 来实现你想要的。

      sapply(X = df, FUN = function(v) {
                                    sapply(X = v,
                                           FUN = function(w) eval(parse(text=w)))
                                   }
        )
      

      旁注

    2. 如果您向 eval 提供不正确的表达式,例如 expression(1, 1/2, 2),则计算结果为最后一个值。这解释了4 4.5 5 输出。正确的 expression(c(1, 1/2, 2)) 评估为预期答案。

    3. 代码lapply(df, function(x) eval(parse(text=x))) 返回一个3 3 2,因为sapply(data.frame(a,b,c), as.numeric) 返回:

           a b c
      [1,] 1 2 1
      [2,] 2 1 3
      [3,] 3 3 2
      

      这些数字对应于因子的levels(),您通过这些因子存储分数。

    【讨论】:

    • 您的解决方案效果很好,而且答案也很有教育意义。非常感谢
    【解决方案3】:

    对于那些寻找单线的人:您可以使用 DOSE 包中的 parse_ratio 将字符分数强制转换为数字。

    library(DOSE)
    
    b <- c("5/2","3","7/2")
    parse_ratio(b)
    [1] 2.5 1.0 3.5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 2015-04-15
      相关资源
      最近更新 更多