Как сказать readr :: read_csv правильно угадать двойной столбец - PullRequest
0 голосов
/ 22 октября 2018

У меня есть данные стока с большим количеством нулевых значений и иногда с ненулевыми двойными значениями.

'readr :: read_csv' угадывает целочисленный тип столбца из-за множества нулей.

Как я могу сделать read_csv, чтобы угадать правильный тип двойного столбца?Я не знаю сопоставления имен переменных заранее, поэтому я не могу дать сопоставление типа имени.

Вот небольшой пример

  # create a column of doubles with many zeros (runoff data)
  #dsTmp <- data.frame(x = c(rep(0.0, 2), 0.5)) # this works
  dsTmp <- data.frame(x = c(rep(0.0, 1e5), 0.5))
  write_csv(dsTmp, "tmp/dsTmp.csv")
  # 0.0 is written as 0 
  # read_csv now guesses integer instead of double and reports 
  # a parsing failure. 
  ans <- read_csv("tmp/dsTmp.csv")
  # the last value is NA instead of 0.5
  tail(ans)

Могу ли я сказать ему, чтобы выбрать более широкую попыткутипы столбцов вместо выдачи ошибки разбора?

Issue 645 упоминает эту проблему, но предоставленный обходной путь существует на стороне записи.Я мало влияю на писательскую сторону.

Ответы [ 3 ]

0 голосов
/ 22 октября 2018

data.table::fread, кажется, работает нормально для этого.

write_csv(dsTmp, ttfile <- tempfile())
ans <- fread(ttfile)
tail(ans)
#      x
# 1: 0.0
# 2: 0.0
# 3: 0.0
# 4: 0.0
# 5: 0.0
# 6: 0.5

Со страницы справки ?fread

Редко, файл может содержать данные более высокого типа встроки вне выборки (упоминается как исключение типа вне выборки).В этом случае fread автоматически перечитает только эти столбцы с самого начала, чтобы у вас не было неудобств, связанных с настройкой colClasses самостоятельно;

0 голосов
/ 23 октября 2018

Я передал код решения r2evans небольшой функции:

read_csvDouble <- function(
  ### read_csv but read guessed integer columns as double
  ... ##<< further arguments to \code{\link{read_csv}}
  , n_max = Inf        ##<< see \code{\link{read_csv}}
  , col_types = cols(.default = col_guess()) ##<< see \code{\link{read_csv}}
  ## the default suppresses the type guessing messages
){
  ##details<< Sometimes, double columns are guessed as integer,  e.g. with
  ## runoff data where there are many zeros, an only occasionally 
  ## positive values that can be recognized as double.
  ## This functions modifies \code{read_csv} by changing guessed integer 
  ## columns to double columns.
  #/12564869/kak-skazat-readr-readcsv-pravilno-ugadat-dvoinoi-stolbets
  colTypes <- read_csv(..., n_max = 3, col_types = col_types) %>% attr("spec")
  isIntCol <- map_lgl(colTypes$cols, identical, col_integer())
  colTypes$cols[isIntCol] <- replicate(sum(isIntCol), col_double())
  ##value<< tibble as returned by \code{\link{read_csv}}
  ans <- read_csv(..., n_max = n_max, col_types = colTypes)
  ans
}
0 голосов
/ 22 октября 2018

Вот две техники.(Подготовка данных внизу. $hp и $vs и далее - это целочисленные столбцы.)

Примечание: я добавляю cols(.default=col_guess()) к большинству вызовов первого раза, чтобы мы не получилибольшое сообщение о том, что read_csv нашел столбцы.Он может быть опущен за счет более шумной консоли.

  1. Принудительное использование всех столбцов с двойной настройкой cols(.default=...) работает безопасно, если вы знаете, что нет-номер в файле:

    read_csv("mtcars.csv", col_types = cols(.default = col_double()))
    # Warning in rbind(names(probs), probs_f) :
    #   number of columns of result is not a multiple of vector length (arg 1)
    # Warning: 32 parsing failures.
    ### ...snip...
    # See problems(...) for more details.
    # # A tibble: 32 x 11
    #      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
    #    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
    #  1  21      NA  160    110  3.9   2.62  16.5     0     1     4     4
    #  2  21      NA  160    110  3.9   2.88  17.0     0     1     4     4
    #  3  22.8    NA  108     93  3.85  2.32  18.6     1     1     4     1
    #  4  21.4    NA  258    110  3.08  3.22  19.4     1     0     3     1
    #  5  18.7    NA  360    175  3.15  3.44  17.0     0     0     3     2
    #  6  18.1    NA  225    105  2.76  3.46  20.2     1     0     3     1
    #  7  14.3    NA  360    245  3.21  3.57  15.8     0     0     3     4
    #  8  24.4    NA  147.    62  3.69  3.19  20       1     0     4     2
    #  9  22.8    NA  141.    95  3.92  3.15  22.9     1     0     4     2
    # 10  19.2    NA  168.   123  3.92  3.44  18.3     1     0     4     4
    # # ... with 22 more rows
    
  2. Изменить только <int> (col_integer()) столбцы, проявив немного больше внимания.Мое использование n_max=50 должно быть сбалансировано.Подобно guess_max=, чем больше, тем лучше.В этом случае, если бы я выбрал n_max=1, то верхняя пара значений mpg предложила бы целые числа, что нормально.Но если у вас есть другие поля, которые неоднозначны с другими классами, вам понадобится больше.Поскольку вы говорите о том, что не хотите читать весь файл, но хотите прочитать «немного», чтобы получить правильное предположение, я думаю, что вы можете использовать разумное значение (100–1000 с?), Чтобыустойчив к chr и lgl.

    types <- attr(read_csv("mtcars.csv", n_max=1, col_types = cols(.default = col_guess())), "spec")
    (intcols <- sapply(types$cols, identical, col_integer()))
    #   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb 
    #  TRUE FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE 
    types$cols[intcols] <- replicate(sum(intcols), col_double())
    

    и окончательному чтению, отметив, что $hp и далее теперь <dbl> (в отличие от чтения данных для подготовки, приведенного ниже).

    read_csv("mtcars.csv", col_types = types)
    # # A tibble: 32 x 11
    #      mpg cyl    disp    hp  drat    wt  qsec    vs    am  gear  carb
    #    <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
    #  1  21   c6     160    110  3.9   2.62  16.5     0     1     4     4
    #  2  21   c6     160    110  3.9   2.88  17.0     0     1     4     4
    #  3  22.8 c4     108     93  3.85  2.32  18.6     1     1     4     1
    #  4  21.4 c6     258    110  3.08  3.22  19.4     1     0     3     1
    #  5  18.7 c8     360    175  3.15  3.44  17.0     0     0     3     2
    #  6  18.1 c6     225    105  2.76  3.46  20.2     1     0     3     1
    #  7  14.3 c8     360    245  3.21  3.57  15.8     0     0     3     4
    #  8  24.4 c4     147.    62  3.69  3.19  20       1     0     4     2
    #  9  22.8 c4     141.    95  3.92  3.15  22.9     1     0     4     2
    # 10  19.2 c6     168.   123  3.92  3.44  18.3     1     0     4     4
    # # ... with 22 more rows
    

Данные:

library(readr)
mt <- mtcars
mt$cyl <- paste0("c", mt$cyl) # for fun
write_csv(mt, path = "mtcars.csv")
read_csv("mtcars.csv", col_types = cols(.default = col_guess()))
# # A tibble: 32 x 11
#      mpg cyl    disp    hp  drat    wt  qsec    vs    am  gear  carb
#    <dbl> <chr> <dbl> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
#  1  21   c6     160    110  3.9   2.62  16.5     0     1     4     4
#  2  21   c6     160    110  3.9   2.88  17.0     0     1     4     4
#  3  22.8 c4     108     93  3.85  2.32  18.6     1     1     4     1
#  4  21.4 c6     258    110  3.08  3.22  19.4     1     0     3     1
#  5  18.7 c8     360    175  3.15  3.44  17.0     0     0     3     2
#  6  18.1 c6     225    105  2.76  3.46  20.2     1     0     3     1
#  7  14.3 c8     360    245  3.21  3.57  15.8     0     0     3     4
#  8  24.4 c4     147.    62  3.69  3.19  20       1     0     4     2
#  9  22.8 c4     141.    95  3.92  3.15  22.9     1     0     4     2
# 10  19.2 c6     168.   123  3.92  3.44  18.3     1     0     4     4
# # ... with 22 more rows
...