R change $xxx.xx to xxx.xx for both positive and negative numbers but don't round

后端 未结 4 1781
我寻月下人不归
我寻月下人不归 2021-01-22 20:36

I have a df where columns 2 and beyond are dollar amounts such as $1004.23, ($1482.40), $2423.94 etc. Similar to the example below:

> df
  id   desc    price
         


        
4条回答
  •  遥遥无期
    2021-01-22 21:26

    Another possible solution which builds on your own attempt and takes into account that you need to transform more columns than in the example:

    d[,-c(1:2)] <- lapply(d[,-c(1:2)], 
                          function(x) as.numeric(gsub('[$,]', '', sub(")", "", sub("(", "-", x, fixed=TRUE), fixed=TRUE))))
    

    which gives:

    > d
      id   desc price price2
    1  0  apple  1.00  -5.90
    2  1 banana -2.25   2.39
    3  2 grapes  1.97  -0.95
    

    Or using a for-loop:

    for(i in 3:ncol(d)){
      d[[i]] <- as.numeric(gsub('[$,]', '', sub(")", "", sub("(", "-", d[[i]], fixed=TRUE), fixed=TRUE)))
    }
    

    Or using the data.table package:

    library(data.table)
    cols <- names(d)[-c(1:2)]
    setDT(d)[, (cols) := lapply(.SD, function(x) as.numeric(gsub('[$,]', '', sub(")", "", sub("(", "-", x, fixed=TRUE), fixed=TRUE)))),
             .SDcols = cols]
    

    Or using the dplyr package:

    library(dplyr)
    d %>% 
      mutate_all(funs(as.numeric(gsub('[$,]', '', sub(")", "", sub("(", "-", ., fixed=TRUE), fixed=TRUE)))), -c(1:2))
    

    which will all give you the same result.


    Used data:

    d <- structure(list(id = 0:2, desc = c("apple", "banana", "grapes"), 
                        price = c("$1.00", "($2.25)", "$1.97"), 
                        price2 = c("($5.9)", "$2.39", "($0.95)")),
                   .Names = c("id", "desc", "price", "price2"), class = "data.frame", row.names = c("1", "2", "3"))
    

提交回复
热议问题