2017-05-30 1624 views
3

我有这样的数据帧,我想改变字符值NUM:R - 将chr值从多列转换为num?

> dput(Df) 
structure(list(`@MeasurementDateGMT` = c("2016-09-01 00:00:00", 
"2016-09-01 01:00:00", "2016-09-01 02:00:00", "2016-09-01 03:00:00", 
"2016-09-01 04:00:00", "2016-09-01 05:00:00", "2016-09-01 06:00:00", 
"2016-09-01 07:00:00", "2016-09-01 08:00:00", "2016-09-01 09:00:00", 
"2016-09-01 10:00:00", "2016-09-01 11:00:00", "2016-09-01 12:00:00", 
"2016-09-01 13:00:00", "2016-09-01 14:00:00", "2016-09-01 15:00:00", 
"2016-09-01 16:00:00", "2016-09-01 17:00:00", "2016-09-01 18:00:00", 
"2016-09-01 19:00:00", "2016-09-01 20:00:00", "2016-09-01 21:00:00", 
"2016-09-01 22:00:00", "2016-09-01 23:00:00"), `@Value` = c("10.9", 
"9.8", "9.9", "14.1", "13.6", "16.5", "15", "18.5", "18", "17", 
"16.6", "12", "12.1", "18.1", "15.9", "15.9", "16.9", "21.6", 
"23.5", "40.7", "16.6", "12.7", "12.4", "12.2")), .Names = c("@MeasurementDateGMT", 
"@Value"), class = "data.frame", row.names = c(NA, 24L)) 

代码转换:

columns <- sapply(Df, is.factor) 
Df[, columns] <- lapply(Df[, columns, drop = FALSE], function(x) as.numeric(as.character(x))) 

结果:

> str(Df) 
'data.frame': 24 obs. of 2 variables: 
$ @MeasurementDateGMT: chr "2016-09-01 00:00:00" "2016-09-01 01:00:00" "2016-09-01 02:00:00" "2016-09-01 03:00:00" ... 
$ @Value    : chr "10.9" "9.8" "9.9" "14.1" ... 

他们仍然chr。我错过了什么?有任何想法吗?

+1

'columns'返回'c(FALSE,FALSE)'。你只是懒洋洋地将一种功能抛诸脑后。见'Df [,列]' – thelatemail

+0

@ikop - 确切地说,OP的代码工作正常。 as.numeric(as.character(...)实际上是转换因子变量的好习惯,可惜在Df中没有任何因素可以开始。: -/ – thelatemail

+0

@thelatemail what结果应该'列'返回? – laukok

回答

2

我们可以使用type.convert

Df[] <- lapply(Df, function(x) type.convert(x, as.is = TRUE)) 
str(Df) 
#'data.frame': 24 obs. of 2 variables: 
#$ @MeasurementDateGMT: chr "2016-09-01 00:00:00" "2016-09-01 01:00:00" "2016-09-01 02:00:00" "2016-09-01 03:00:00" ... 
#$ @Value    : num 10.9 9.8 9.9 14.1 13.6 16.5 15 18.5 18 17 

...

如果我们需要将“日期时间”列转换,

Df[[2]] <- as.POSIXct(Df[[2]]) 

由于列在OP的帖子都character,我们并不需要转换它适用于characctertype.convert否则使用type.convert(as.character(x), ..


好吧,如果我们需要dplyr做到这一点

library(dplyr) 
res <- Df %>% 
     mutate_all(funs(type.convert(as.character(.), as.is = TRUE))) 
str(res) 
#'data.frame': 24 obs. of 2 variables: 
#$ @MeasurementDateGMT: chr "2016-09-01 00:00:00" "2016-09-01 01:00:00" "2016-09-01 02:00:00" "2016-09-01 03:00:00" ... 
#$ @Value    : num 10.9 9.8 9.9 14.1 13.6 16.5 15 18.5 18 17 ... 

或者另一种选择是data.table

library(data.table) 
setDT(Df)[, lapply(.SD, function(x) type.convert(x, as.is = TRUE))] 
+0

谢谢你的回答。日期是'chr'。我怎样才能把它改成'POSIXct,format'? – laukok

+1

@teelou你的标题是将'chr'转换为'numeric'列。所以,我认为你可以稍后转换'datetime'列 – akrun

1

您可以使用dplyr::mutate_if其应用功能(在这种情况下as.numeric)所有列那满足谓词函数(在这种情况下为is.character)。

library(dplyr) 

df %>% 
    janitor::clean_names() %>% # removes the "@" from names since that messes up mutate_if 
    tibble::as_tibble() %>% # just for the nice printing 
    mutate_if(is.character, as.numeric) 

#> Warning in eval(substitute(expr), envir, enclos): NAs introduced by 
#> coercion 

#> # A tibble: 24 x 2 
#> x_measurementdategmt x_value 
#>     <dbl> <dbl> 
#> 1     NA 10.9 
#> 2     NA  9.8 
#> 3     NA  9.9 
#> 4     NA 14.1 
#> 5     NA 13.6 
#> 6     NA 16.5 
#> 7     NA 15.0 
#> 8     NA 18.5 
#> 9     NA 18.0 
#> 10     NA 17.0 
#> # ... with 14 more rows 

但对于第一列,因为它是一个日期时间以上无法正常工作。它只被设置为NAas.numeric,因为它包含非数字字符。相反,您可能应该将其更改为日期时间变量。

df %>% 
    janitor::clean_names() %>% 
    tibble::as_tibble() %>% 
    mutate(x_measurementdategmt = lubridate::as_datetime(x_measurementdategmt)) %>% 
    mutate_if(is.character, as.numeric) 
#> # A tibble: 24 x 2 
#> x_measurementdategmt x_value 
#>     <dttm> <dbl> 
#> 1 2016-09-01 04:00:00 10.9 
#> 2 2016-09-01 05:00:00  9.8 
#> 3 2016-09-01 06:00:00  9.9 
#> 4 2016-09-01 07:00:00 14.1 
#> 5 2016-09-01 08:00:00 13.6 
#> 6 2016-09-01 09:00:00 16.5 
#> 7 2016-09-01 10:00:00 15.0 
#> 8 2016-09-01 11:00:00 18.5 
#> 9 2016-09-01 12:00:00 18.0 
#> 10 2016-09-01 13:00:00 17.0 
#> # ... with 14 more rows