我正在尝试将以分数形式存储为字符的数字数据帧转换为十进制形式的数字。 (还有一些整数,也存储为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[] <- 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[] <- 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
非常感谢!
答案 0 :(得分: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是不应评估的元素向量。
答案 1 :(得分:1)
首先,您应该防止角色转变为data.frame()
df&lt; - data.frame(a,b,c,stringsAsFactors = F)
然后,您可以在sapply/lapply
内包含一个简单的lapply
来实现您想要的效果。
sapply(X = df, FUN = function(v) {
sapply(X = v,
FUN = function(w) eval(parse(text=w)))
}
)
附注
如果您向eval
提供expression(1, 1/2, 2)
等不正确的表达式,则表示评估为最后一个值。这解释了4 4.5 5
输出。正确的expression(c(1, 1/2, 2))
评估预期答案。
代码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()
因子。
答案 2 :(得分:0)
对于那些寻找单行的人:您可以使用 DOSE 包中的 parse_ratio
将字符分数强制转换为数字。
library(DOSE)
b <- c("5/2","3","7/2")
parse_ratio(b)
[1] 2.5 1.0 3.5