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 в текстовом редакторе, цифры были "вокруг". Но он все еще работал.