Изменить тип данных для каждого столбца данных на основе данных с предопределенными типами данных в R - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть значение dataframe, состоящее из символьных столбцов и свойства dataframe, состоящее из имен столбцов значений dataframe и предопределенного типа данных. Мне нужно проверить, соответствуют ли типы данных значений предопределенному типу данных. Поэтому я хочу изменить типы данных в кадре данных значений на основе предопределенных типов данных в кадре данных свойств в автоматическом режиме с использованием map (), apply () или a для l oop, предпочтительно аккуратного (стих) решения.

Ниже приведен пример, но фактический набор данных имеет гораздо больше столбцов / свойств.

# Libraries
library(dplyr)

# Seed
set.seed(12345)

# Property example
properties <- 
  tibble(property = c("a", "b", "c"),
         datatype = c("logical", "integer", "double"))

# Values example
values <- 
  tibble(a = sample(c("TRUE", "FALSE", "CORRECT"), 10, replace = TRUE),
         b = as.character(sample(c(1:9, 1.4), 10)),
         c = sample(c(-1.5:1.5, "word"), 10, replace = TRUE))

properties
## A tibble: 3 x 2
#  property datatype
#  <chr>    <chr>   
#1 a        logical
#2 b        integer 
#3 c        double  

values
## A tibble: 10 x 3
#   a       b     c    
#   <chr>   <chr> <chr>
# 1 FALSE   7     -1.5 
# 2 CORRECT 1     word 
# 3 FALSE   8     1.5  
# 4 FALSE   1.4   -0.5 
# 5 TRUE    6     -0.5 
# 6 CORRECT 9     1.5  
# 7 FALSE   4     0.5  
# 8 FALSE   2     1.5  
# 9 CORRECT 3     -1.5 
#10 FALSE   5     -1.5 

В качестве части моей проверки я буду сравнивать количество NA на столбец до и после преобразования. , Это создает другую проблему, так как двойные значения будут автоматически преобразованы в целые числа, в то время как это должно стать NA, потому что это неверный тип данных (столбец b, строка 4).

# Prefered result
tibble(a = c(FALSE, NA, FALSE, FALSE, TRUE, NA, FALSE, FALSE, NA, FALSE), 
       b = c(7L, 1L, 8L, NA_integer_, 6L, 9L, 4L, 2L, 3L, 5L), 
       c = c(-1.5, NA, 1.5, -0.5, -0.5, 1.5, 0.5, 1.5, -1.5, -1.5))
## A tibble: 10 x 3
#   a         b     c
#   <lgl> <int> <dbl>
# 1 FALSE     7  -1.5
# 2 NA        1  NA  
# 3 FALSE     8   1.5
# 4 FALSE    NA  -0.5
# 5 TRUE      6  -0.5
# 6 NA        9   1.5
# 7 FALSE     4   0.5
# 8 FALSE     2   1.5
# 9 NA        3  -1.5
#10 FALSE     5  -1.5

Вся помощь очень ценится !

Ответы [ 2 ]

1 голос
/ 20 апреля 2020

РЕДАКТИРОВАТЬ: Добавить dplyr решение

properties <- mutate(properties,func_name =paste0("as.",datatype) )


values %>% 
  mutate_all(function(x) match.fun(properties$func_name[match(deparse(substitute(x)),properties$property)])(x))
#> Warning in (function (x) : NAs introduced by coercion
#> # A tibble: 10 x 3
#>    a         b     c
#>    <lgl> <int> <dbl>
#>  1 FALSE     7  -1.5
#>  2 NA        1  NA  
#>  3 FALSE     8   1.5
#>  4 FALSE     1  -0.5
#>  5 TRUE      6  -0.5
#>  6 NA        9   1.5
#>  7 FALSE     4   0.5
#>  8 FALSE     2   1.5
#>  9 NA        3  -1.5
#> 10 FALSE     5  -1.5

В основном это можно сделать с помощью match.fun(funcname)

# Libraries
library(dplyr)
library(data.table)

# Seed
set.seed(12345)

# Property example
properties <- 
  tibble(property = c("a", "b", "c"),
         datatype = c("logical", "integer", "double"))
       # datatype = c("boolean", "integer", "double"))
# Values example
values <- 
  tibble(a = sample(c("TRUE", "FALSE", "CORRECT"), 10, replace = TRUE),
         b = as.character(sample(c(1:9, 1.4), 10)),
         c = sample(c(-1.5:1.5, "word"), 10, replace = TRUE))


setDT(properties)
setDT(values)

properties[,func_name:=paste0("as.",datatype)]

for (i in names(values)){
  set(values,j = i,value=match.fun(properties[property==i,func_name])(values[[i]]))

  print(match.fun(properties[property==i,func_name]))
}
#> function (x, ...)  .Primitive("as.logical")
#> function (x, ...)  .Primitive("as.integer")
#> Warning in match.fun(properties[property == i, func_name])(values[[i]]): NAs
#> introduced by coercion
#> function (x, ...)  .Primitive("as.double")

values
#>         a b    c
#>  1: FALSE 7 -1.5
#>  2:    NA 1   NA
#>  3: FALSE 8  1.5
#>  4: FALSE 1 -0.5
#>  5:  TRUE 6 -0.5
#>  6:    NA 9  1.5
#>  7: FALSE 4  0.5
#>  8: FALSE 2  1.5
#>  9:    NA 3 -1.5
#> 10: FALSE 5 -1.5

Создано в 2020 году -04-20 с помощью пакета Представить (v0.3.0)

Я изменил ваш "логический" на "логический", так как нет функции с именем as.boolean

Вы также можете попробовать as.boolean <- as.logical, чтобы избежать изменения существующих кодов.

0 голосов
/ 20 апреля 2020

Вы можете попробовать следующий код и посмотреть, служит ли он вашей цели.

# Libraries
library(dplyr)

# Seed
set.seed(12345)

# Property example
properties <- 
  tibble(property = c("a", "b", "c"),
         datatype = c("logical", "integer", "double"))

# Values example
values <- 
  tibble( a = as.logical(sample(c("TRUE", "FALSE", "CORRECT"), 10, replace = TRUE)),
          b = sample(c(1:9, 1.4), 10) %>% ifelse( . -floor(.) == 0 , . ,NA ),
          c = as.numeric(sample(c(-1.5:1.5, "word"), 10, replace = TRUE)) )

Warning message:
In eval_tidy(xs[[i]], unique_output) : NAs introduced by coercion
values
# A tibble: 10 x 3
   a         b     c
   <lgl> <dbl> <dbl>
 1 FALSE     6  -1.5
 2 TRUE     NA  -0.5
 3 TRUE      3   1.5
 4 FALSE     5   0.5
 5 TRUE      2  -1.5
 6 NA        8   0.5
 7 TRUE      7   0.5
 8 TRUE      9   1.5
 9 NA        1  -1.5
10 NA        4  NA

Вы можете проверить, работает ли он для вас, ура!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...