如何在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) )