Readr: Отключить научную нотацию в write_csv
Я использую R для обработки данных переписи, которая использует действительно длинные числовые ГЕОИДЫ для идентификации географических регионов. Проблема, с которой я сталкиваюсь, заключается в том, чтобы записывать обработанные данные с помощью write_csv
(из пакета readr
), он записывает эти ГЕОИДЫ в научной нотации. Есть ли способ обойти это?
Примечание. Я могу переключить отображение научной нотации на консоли R, установив параметр scipen
на достаточно большое значение. Но этот параметр, похоже, не распространяется на библиотеку readr
.
Вот набор данных игрушек:
library(dplyr)
library(readr) # which is the package with write_csv
(tbl_df(data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1))))
Source: local data frame [6 x 1]
GEOID
1 60150001022000
2 60150001022001
3 60150001022002
4 60150001022003
5 60150001022004
6 60150001022005
write_csv((tbl_df(data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1)))), "test.csv")
Это то, что я получаю в настоящее время. Я ищу способ получить те же номера, что и выше:
GEOID
6.02E+13
6.02E+13
6.02E+13
6.02E+13
6.02E+13
6.02E+13
Ответы
Ответ 1
Я написал pull request с патчем, чтобы улучшить контроль над научной нотой в write_csv
.
С этим патчем у вас будет аргумент int_use_scientific=FALSE
в write_csv
, который решит вашу проблему. Надеюсь, что в конечном итоге он будет объединен.
Ответ 2
Вероятно, было бы безопаснее использовать значения символов:
X <- tbl_df(data.frame(GEOID = as.character(seq(from=60150001022000, to=60150001022005))))
write_csv(X, "test.csv")
Немного иронично, что функция write_csv принуждает часть своего вывода к символьным значениям, но не к числовым столбцам. Только если столбец пройдет тест is.object
, он будет принудительным. Кажется, что нет переключателя для броска, который сохранит максимальную точность. Функции write.table
и его дочерние функции write.csv
имеют несколько переключателей, которые позволяют подавлять кавычки и другие настройки, которые позволяют адаптировать вывод, но write_csv
имеет очень мало таких.
Вы можете обмануть write_csv, считая, что числовой столбец является чем-то более сложным, и это приводит к выводу as.character
, хотя и с кавычками.
class(X[[1]])<- c("num", "numeric")
vapply(X, is.object, logical(1))
#GEOID
# TRUE
write_csv(X, "")
#[1] #"\"GEOID\"\n\"60150001022000\"\n\"60150001022001\"\n\"60150001022002\"\n\"60150001022003\"\n\"60150001022004\"\n\"60150001022005\"\n"
В качестве передового опыта я не согласен с вашим выбором: настаивать на том, что идентификационные переменные остаются числовыми. Слишком много насилия, которое может быть применено к этому режиму хранения для объекта. Вам не нужны никакие арифметические операции для ID-переменной.
Ответ 3
Я предпочел бы перекодировать такие столбцы, чтобы набрать int
, потому что если так write_*
больше не будет использовать научную кодировку. Чтобы преобразовать все числовые столбцы за один проход (например, если вы имеете дело с матрицей counts), вы можете сделать:
require(dplyr)
tbl_df = mutate_if(tbl_df, is.numeric, as.integer)
Ответ 4
Я предлагаю вам использовать
write.csv((tbl_df(data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1)))), "test.csv")
вместо
write_csv((tbl_df(data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1)))), "test.csv")
Если я открою test.csv, он откроет файл в Excel. Excel превращает его в научную нотацию.
Когда я щелкаю правой кнопкой и открываю с помощью блокнота, он выглядит хорошо, и я вижу исходные номера без научной нотации.
Ответ 5
Используйте bit64, это класс S3 для векторов для 64-битных целых чисел
library(dplyr)
library(readr)
options(digits = 22)
tbl_df <- data.frame(GEOID = seq(from=60150001022000, to=60150001022005, 1))
> tbl_df
GEOID
1 60150001022000
2 60150001022001
3 60150001022002
4 60150001022003
5 60150001022004
6 60150001022005
library(bit64)
tbl_df$GEOID <- as.integer64(tbl_df$GEOID)
write_csv(tbl_df,'test.csv')
Если вы снова прочтете эти данные в R, он назначит правильный тип данных.
dfr <- read_csv('test.csv')
> dfr
Source: local data frame [6 x 1]
GEOID
1 60150001022000
2 60150001022001
3 60150001022002
4 60150001022003
5 60150001022004
6 60150001022005
> str(tbl_df)
'data.frame': 6 obs. of 1 variable:
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 6 obs. of 1 variable:
$ GEOID: num 6.02e+13 6.02e+13 6.02e+13 6.02e+13 6.02e+13 ...
Надеюсь, это поможет. Я открыл csv в текстовом редакторе, цифры были "вокруг". Но он все еще работал.