Я работаю с почтовыми индексами, у которых, конечно, есть ведущие нули. Я правильно загружаю фрейм данных, чтобы сохранить ведущие нули в R, но этап загрузки, похоже, завершился ошибкой. Вот что я имею в виду:
Вот мой файл minimal.csv:
zip,val
07030,10
10001,100
90210,1000
60602,10000
Вот код R
require("bigrquery")
filename <- "minimal.csv"
tablename <- "as_STRING"
ds <- bq_dataset(project='myproject', dataset = "zips")
Я также правильно устанавливаю тип в своей схеме, чтобы ожидать их в виде строк.
# first pass
df <- read.csv(filename, stringsAsFactors=F)
# > df
# zip val
# 1 7030 10
# 2 10001 100
# 3 90210 1000
# 4 60602 10000
# uh oh! Let's fix it!
cols <- unlist(lapply(df, class))
cols[[1]] <- "character" # make zipcode a character
# then reload
df2 <- read.csv(filename, stringsAsFactors=F, colClasses=cols)
# > df2
# zip val
# 1 07030 10
# 2 10001 100
# 3 90210 1000
# 4 60602 10000
# much better! You can see my zips are now strings.
Однако, когда я пытаюсь загрузить строки, интерфейс bigrquery жалуется, что я загружаю целые числа, а это не так. Вот схема, ожидающая строк:
# create schema
bq_table_create(bq_table(ds, tablename), fields=df2) # using df2, which has strings
# now prove it got the strings right:
> bq_table_meta(bq_table(ds, tablename))$schema$fields
[[1]]
[[1]]$name
[1] "zip"
[[1]]$type
[1] "STRING" # GOOD, ZIP IS A STRING!
[[1]]$mode
[1] "NULLABLE"
[[2]]
[[2]]$name
[1] "val"
[[2]]$type
[1] "INTEGER"
[[2]]$mode
[1] "NULLABLE"
Пришло время загрузить ....
bq_table_upload(bq_table(ds, tablename), df2) # using df2, with STRINGS
Error: Invalid schema update. Field zip has changed type from STRING to INTEGER [invalid]
Хм? Что это за недопустимое обновление схемы, и как я могу остановить его от попытки изменить мои строки, которые содержат данные и схема, на целые числа, которые мои данные не содержат, а схема - нет?
Происходит ли сериализация javascript, которая возвращает мои строки к целым числам?





Это потому, что BigQuery автоматически обнаружит схему, если она не указана. Это можно решить, указав аргумент fields, например (см. этот похожий вопрос для более подробной информации):
bq_table_upload(bq_table(ds, tablename), df2,fields = list(bq_field("zip", "string"),bq_field("val", "integer")))
Обновлено:
Заглянув в код, bq_table_upload вызывает bq_perform_upload, который принимает аргумент fields как схему. В конце он анализирует data frame как файл JSON и загружает его в BigQuery.
@Mittenchops В своем ответе я добавил еще несколько деталей кода. Я мог бы сказать, что самый простой способ - предоставить аргумент fields функции, но вы можете захотеть отредактировать код для вашего варианта использования.
Просто меняя:
bq_table_upload(tab, df)
к
bq_table_upload(tab, df, fields=df)
работает.
Оно делает! Спасибо!
Спасибо. Это полезный ответ. Это также очень странно для пакета, почему интерфейс по умолчанию автоматически определяет, а не использует типы данных, заданные фреймом данных?