如何在R中舍入包含一些字符变量的data.frame?
我有一个数据框,我希望对所有的数字进行四舍五入(准备导出)。这一定很简单,但我遇到了一些问题,因为数据帧的某些位不是数字。例如,我想在下面的示例中将数字四舍五入到最接近的整数:如何在R中舍入包含一些字符变量的data.frame?,r,R,我有一个数据框,我希望对所有的数字进行四舍五入(准备导出)。这一定很简单,但我遇到了一些问题,因为数据帧的某些位不是数字。例如,我想在下面的示例中将数字四舍五入到最接近的整数: ID = c("a","b","c","d","e") Value1 = c("3.4","6.4","8.7","1.1","0.1") Value2 = c("8.2","1.7","6.4","1.9","10.3") df<-data.frame(ID,Value1,Value2) ID=c(“a”、“b
ID = c("a","b","c","d","e")
Value1 = c("3.4","6.4","8.7","1.1","0.1")
Value2 = c("8.2","1.7","6.4","1.9","10.3")
df<-data.frame(ID,Value1,Value2)
ID=c(“a”、“b”、“c”、“d”、“e”)
值1=c(“3.4”、“6.4”、“8.7”、“1.1”、“0.1”)
值2=c(“8.2”、“1.7”、“6.4”、“1.9”、“10.3”)
df为什么不直接使用ID作为行名呢
。。。并从value1和value2数据中取出“'s”
请尝试以下方法:
ID = c("a","b","c","d","e")
Value1 = c(3.4,6.4,8.7,1.1,0.1)
Value2 = c(8.2,1.7,6.4,1.9,10.3)
df<-data.frame(ID,Value1,Value2,row.names=TRUE)
> df
Value1 Value2
a 3.4 8.2
b 6.4 1.7
c 8.7 6.4
d 1.1 1.9
e 0.1 10.3
> str(df)
'data.frame': 5 obs. of 2 variables:
$ Value1: num 3.4 6.4 8.7 1.1 0.1
$ Value2: num 8.2 1.7 6.4 1.9 10.3
首先确保数字列为数字:
ID = c("a","b","c","d","e")
Value1 = as.numeric(c("3.4","6.4","8.7","1.1","0.1"))
Value2 = as.numeric(c("8.2","1.7","6.4","1.9","10.3"))
df<-data.frame(ID,Value1,Value2, stringsAsFactors = FALSE)
ID=c(“a”、“b”、“c”、“d”、“e”)
值1=数值形式(c(“3.4”、“6.4”、“8.7”、“1.1”、“0.1”))
值2=如数字(c(“8.2”、“1.7”、“6.4”、“1.9”、“10.3”))
df认识到这是一个老问题,一个答案是可以接受的,我想提供另一个解决方案,因为这个问题在谷歌上显示为排名靠前的结果
更一般的解决方案是创建一个单独的函数,搜索所有数值变量,并将其舍入到指定的位数:
round_df <- function(df, digits) {
nums <- vapply(df, is.numeric, FUN.VALUE = logical(1))
df[,nums] <- round(df[,nums], digits = digits)
(df)
}
其他答案不能完全回答OP的问题,因为它们假设示例数据与OP提供的数据不同
如果我们逐字阅读这个问题,我们想要一个通用的解决方案,可以找到其中包含数字的列(任何向量类型),将它们转换为数字,然后执行另一个数字操作,例如舍入。我们可以使用purrr:dmap
这样做:
以下是OP提供的数据,其中所有COL都是因子(一个恼人的默认值,但我们可以处理它):
这在数据帧有大量列的情况下可能很有用,并且我们有许多字符/因子类型的列,这些列都是我们想要的数字,但是手工操作太繁琐了。我知道这是一个很晚的答复,但我也有同样的问题。在进行一些搜索后,我发现这是最优雅的解决方案n:
data.frame(lapply(x, function(y) if(is.numeric(y)) round(y, 2) else y))
解决方案最初来自:
让·V·亚当斯
统计员
美国地质调查局
五大湖科学中心
东斯坦菲斯特路223号
美国威斯康星州安提哥54409
这是我喜欢使用的单行程序:
(这将只对classes
参数中指定的类类型的列应用round
函数)
df2上面的答案指出了最初问题中的几个障碍,这使得问题比只将多列四舍五入更加复杂,主要是:
数字以字符形式输入,并且
data.frame()
default将字符数转换为因子
Ben的回复详细说明了如何处理这些问题,并应用了purr::dmap()
。purrr
包已被修改,而dmap
函数已被弃用(支持map\u df()
)。
还有一个更新的函数,modify_if()
,它可以解决对多个数字列进行舍入的问题,因此我想更新这个答案
我将以数字的形式输入数据,在四舍五入中再添加几个数字,以使示例更广泛地适用:
df <- data.frame(ID = c("a","b","c","d","e"),
Value1 =c(3.4532897,6.41325,8.71235,1.115,0.115),
Value2 = c(8.2125,1.71235,6.4135,1.915,10.3235))
只需将四舍五入(数字=0)
更改为适当的十进制空格
modify_if(df, ~is.numeric(.), ~round(., 2))
ID Value1 Value2
1 a 3.45 8.21
2 b 6.41 1.71
3 c 8.71 6.41
4 d 1.12 1.92
5 e 0.12 10.32
有关语法的更多文档,请参阅
这也可以通过使用base R apply函数分两步完成,即为列创建索引(NUMVAR),然后通过标准索引仅修改这些列:
numVars <- sapply(df, is.numeric)
ID Value1 Value2
FALSE TRUE TRUE
df[, numVars] <- lapply(df[, numVars], round, 0)
df
ID Value1 Value2
1 a 3 8
2 b 6 2
3 c 9 6
4 d 1 2
5 e 0 10
numVars我认为现在最简洁的方法是使用dplyr
library(dplyr)
df %>%
mutate_if(is.numeric, round)
这将使数据框中的所有数字列都四舍五入。请注意,上面提出的一些解决方案不考虑行名称,这意味着它们丢失了
例如,尝试:
df <- data.frame(v1 = seq(1.11, 1.20, 0.01), v2 = letters[1:10])
row.names(df) = df$v2
请注意,行名称不再存在
Akhmed的建议保留行名,因为行名可以替换。舍入对“数字”而不是字符有意义。您必须将Value1
和Value2
转换为numeric
,例如舍入(如.numeric(Value1),0)
可以完成这项工作,但您没有指定如何进行舍入(查找trunc
、天花
或floor
)中的一个。如果您知道要对哪些列进行舍入并已转换,还可以执行df[,c('Value1','Value2')。此外,如果您只想查找数字列并舍入,可以使用df[,sapply(df,is.numeric)]谢谢Tyler!这正是我想要的-你帮我节省了很多时间!!这是一个标准解决方案。请注意,numVars modify if似乎不存在于当前的purrr包中。下载并加载purrr后,我收到错误消息,说找不到modify\u ifpackage@Mark嗯……我刚检查过,它是当前的CRAN版本(purrr 0.2.3)。我稍微编辑了命令,使其成为purrr::modify_if
,这样您就不必加载包了。看看这是否有帮助。@标记它看起来也像是在当前的Github verson中。但是,tidyverse现在变化太大了,我现在主要使用CRAN。太棒了!库(dplyr);df%>%mutate_if(is.numeric,round,digits=3)
这是一个我从未想到过的绝妙、简单的解决方案!谢谢!
df_numerics
ID Value1 Value2
1 1 3 8
2 2 6 2
3 3 9 6
4 4 1 2
5 5 0 10
str(df_numerics)
'data.frame': 5 obs. of 3 variables:
$ ID : num 1 2 3 4 5
$ Value1: num 3 6 9 1 0
$ Value2: num 8 2 6 2 10
data.frame(lapply(x, function(y) if(is.numeric(y)) round(y, 2) else y))
df2 <- rapply(object = df, f = round, classes = "numeric", how = "replace", digits = 0)
df <- data.frame(ID = c("a","b","c","d","e"),
Value1 =c(3.4532897,6.41325,8.71235,1.115,0.115),
Value2 = c(8.2125,1.71235,6.4135,1.915,10.3235))
purrr::modify_if(df, ~is.numeric(.), ~round(., 0))
ID Value1 Value2
1 a 3 8
2 b 6 2
3 c 9 6
4 d 1 2
5 e 0 10
modify_if(df, ~is.numeric(.), ~round(., 2))
ID Value1 Value2
1 a 3.45 8.21
2 b 6.41 1.71
3 c 8.71 6.41
4 d 1.12 1.92
5 e 0.12 10.32
numVars <- sapply(df, is.numeric)
ID Value1 Value2
FALSE TRUE TRUE
df[, numVars] <- lapply(df[, numVars], round, 0)
df
ID Value1 Value2
1 a 3 8
2 b 6 2
3 c 9 6
4 d 1 2
5 e 0 10
library(dplyr)
df %>%
mutate_if(is.numeric, round)
df <- data.frame(v1 = seq(1.11, 1.20, 0.01), v2 = letters[1:10])
row.names(df) = df$v2
data.frame( lapply(df, function(y) if(is.numeric(y)) round(y, 2) else y) )