импорт фреда пустой как NA - PullRequest
1 голос
/ 03 октября 2019

Я пытаюсь импортировать csv с пробелами, прочитанными как "". К сожалению, все они теперь читают как "NA".

Чтобы лучше продемонстрировать проблему, я также показываю, как NA, "NA" и "" все отображаются на одно и то же (кроме самого нижнего примера), что предотвратит простоеОбходной путь dt[is.na(dt)] <- ""

> write.csv(matrix(c("0","",NA,"NA"),ncol = 2),"MRE.csv")

При открытии этого в блокноте это выглядит следующим образом

"","V1","V2"
"1","0",NA
"2","","NA"

Итак, читая это обратно ...

> fread("MRE.csv")
   V1 V1 V2
1:  1  0 NA
2:  2 NA NA

Документация кажетсяпредложить это, но это не работает, как описано

> fread("MRE.csv",na.strings = NULL)
   V1 V1 V2
1:  1  0 NA
2:  2 NA NA

Также пробовал это, который читает NA как фактический NA, но проблема остается для пустой строки, которая читается как "NA"

> fread("MRE.csv",colClasses=c(V1="character",V2="character"))
   V1 V1   V2
1:  1  0 <NA>
2:  2 NA   NA

> fread("MRE.csv",colClasses=c(V1="character",V2="character"))[,V2]
[1] NA   "NA"

data.table версия 1.11.4

R версия 3.5.1

1 Ответ

2 голосов
/ 03 октября 2019

Здесь возможно несколько вещей:

  1. Независимо от того, что вы здесь пишете "0", функция чтения (fread) выводится на основании рассмотрения частифайл. Это не редкость (readr делает это тоже) и является управляемым (с colClasses=).

  2. Это может быть уникально для вашего вопроса здесь (а не для ваших реальных данных), но ваш вызов write.csv неявно помещает буквенные буквы NA в файл (не путать с "NA", где у вас есть буквенная строка). Это может сбивать с толку, даже если вы переопределяете с помощью colClasses=.

  3. Вы, возможно, уже знаете это, но поскольку fread выводит, что эти столбцы действительно integer классы,тогда они не могут содержать пустые строки: однажды определенная как числовой столбец, все, что не похоже на число, будет NA.

Давайте переделаем вашу первую сторону, генерирующую csv, чтобы убедиться,мы не путаем ситуацию.

write.csv(matrix(c("0","",NA,"NA"),ncol = 2), "MRE.csv", na="")

(ниже я использую %>% оператор трубы *1032* просто для презентации, это не требуется.)

Первый пример демонстрирует умозаключение fread. Второй показывает наше переопределение этого поведения, и теперь у нас есть пустые строки в каждом NA месте, которое не является литеральной строкой "NA".

fread("MRE.csv") %>% str
# Classes 'data.table' and 'data.frame':    2 obs. of  3 variables:
#  $ V1: int  1 2
#  $ V1: int  0 NA
#  $ V2: logi  NA NA
#  - attr(*, ".internal.selfref")=<externalptr> 

fread("MRE.csv", colClasses="character") %>% str
# Classes 'data.table' and 'data.frame':    2 obs. of  3 variables:
#  $ V1: chr  "1" "2"
#  $ V1: chr  "0" ""
#  $ V2: chr  "" "NA"
#  - attr(*, ".internal.selfref")=<externalptr> 

Это также можно контролироватьна основе столбца. Одна из проблем этого примера в том, что fread по какой-то причине заставляет столбец с именами строк называться V1, так же, как и следующий столбец. Для меня это похоже на ошибку, возможно, вы можете посмотреть на проблемы Rdatatable и, возможно, опубликовать новую. (Я могу ошибаться, возможно, это преднамеренное / известное поведение.)

Из-за этого переопределение для столбца, по-видимому, останавливается при первом появлении имени столбца.

fread("MRE.csv", colClasses=c(V1="character", V2="character")) %>% str
# Classes 'data.table' and 'data.frame':    2 obs. of  3 variables:
#  $ V1: chr  "1" "2"
#  $ V1: int  0 NA
#  $ V2: chr  "" "NA"
#  - attr(*, ".internal.selfref")=<externalptr> 

Одним из способов решения этой проблемы является использование неназванного вектора, требующего того же количества классов, что и количество столбцов:

fread("MRE.csv", colClasses=c("character","character","character")) %>% str
# Classes 'data.table' and 'data.frame':    2 obs. of  3 variables:
#  $ V1: chr  "1" "2"
#  $ V1: chr  "0" ""
#  $ V2: chr  "" "NA"
#  - attr(*, ".internal.selfref")=<externalptr> 

Другой способ (спасибо @thelatemail) - это список:

fread("MRE.csv", colClasses=list(character=2:3)) %>% str
# Classes 'data.table' and 'data.frame':    2 obs. of  3 variables:
#  $ V1: int  1 2
#  $ V1: chr  "0" ""
#  $ V2: chr  "" "NA"
#  - attr(*, ".internal.selfref")=<externalptr> 

Примечание: если вам нужно сохранить их в виде целых чисел / чисел, то:

  1. , если вас интересует, как это повлияет на последующие вычисления, тогда вы можете:

    1. исправить источник данных таким образом, чтобы нули не предоставлялись;
    2. отфильтровать неполные наблюдения (строки);или
    3. исправьте расчеты, чтобы разумно обрабатывать отсутствующие данные.
  2. , если вас беспокоит то, как он выглядит в отчете, то каким бы инструментом вы ни пользовалисьдля рендеринга в вашем отчете должен быть предусмотрен механизм отображения NA значений;Например, установка options(knitr.kable.NA="") перед knitr::kable(...) представит их в виде пустых строк.

  3. , если вас беспокоит то, как это выглядит на вашей консоли , у вас естьдва варианта:

    1. вмешиваться в данные путем итерации по каждому (предполагаемому) столбцу и изменения значений NA на "";это работает только на character столбцах и является необратимым;или
    2. написать свой собственный подкласс data.frame, который меняет способ его отображения на консоли;выгода для этого состоит в том, что это не разрушительно;проблема заключается в том, что вам необходимо переклассифицировать каждый объект, где вы хотите, чтобы это поведение, и большинство (если не все) функции, которые выводят кадры, вероятно, непреднамеренно удалят или пропустят этот класс из вашего ввода. (Для этого вам нужно написать метод S3 print для вашего подкласса.)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...