Преобразовать символьную колонку в data.table в bigz Integer - PullRequest
0 голосов
/ 09 октября 2018

Я работаю с data.table, считанным из файла .txt с fread.data.table содержит некоторое количество integer столбцов, а также столбец с очень большими целыми числами, которые я намерен хранить как bigz.Тем не менее, fread будет читать только большие целые числа как character, если я планирую сохранить все цифры (и я так и сделаю).

#Something to the effect of (run not needed):
#fread(file = FILENAME.txt, header=TRUE, colClasses = c(rep("integer", 10), "character"), data.table = TRUE)

Кроме того, я работаю с довольно большим набором данных.Моя основная проблема - преобразование столбца character в столбце data.table в столбец bigz без создания нового объекта.

Вот игрушечный пример, которыйдемонстрирует мою проблему.Во-первых, я знаю, что data.table s может иметь bigz столбцы - IF они вводятся в новый объект.

library(gmp)
library(data.table)
exa = as.bigz(2)^80          #A very large number          
cha = as.character(exa)      #The same number in character form
(good = data.table(nums = 1:3, lets = letters[1:3], bigs = rep(exa, 3)))   
str(good)                    #Notice "bigs" is type bigz (and raw?)

Однако, если столбец character должен быть преобразован в столбец bigz на лету, возникает ошибка.Синтаксис в этих методах преобразования «работает» в столбце numeric nums, если as.bigz заменен на as.character.

(bad = data.table(nums = 1:3, lets = letters[1:3], bigs = rep(cha, 3)))
str(bad)
#Method 1
bad[,bigs:=as.bigz(bigs)]
#Method 2 (re-create data.table first)
bad = data.table(nums = 1:3, lets = letters[1:3], bigs = rep(cha, 3))
set(bad, j="bigs", value = as.bigz(bad$bigs))

Ошибка ниже.Похоже, что проблема связана с тем, что bigz целые числа хранятся как raw, хотя я не уверен, откуда исходит 64 - exa имеет 24 цифры.

Warning messages:
1: In `[.data.table`(bad, , `:=`(bigs, as.bigz(bigs))) :
Supplied 64 items to be assigned to 3 items of column 'bigs' (61 unused)
2: In `[.data.table`(bad, , `:=`(bigs, as.bigz(bigs))) :
Coerced 'raw' RHS to 'character' to match the column's type. Either change the target column ['bigs'] to 'raw' first (by creating a new 'raw' vector length 3 (nrows of entire table) and assign that; i.e. 'replace' column), or coerce RHS to 'character' (e.g. 1L, NA_[real|integer]_, as.*, etc) to make your intent clear and for speed. Or, set the column type correctly up front when you create the table and stick to it, please.

У меня есть обходной путь, но он требует создания нового объекта (и удаления старого).

(bad = data.table(nums = 1:3, lets = letters[1:3], bigs = rep(cha, 3)))
meh = data.table(as.data.frame(bad)[,-3], bigs = as.bigz(bad$bigs))
rm(bad)
str(meh)
identical(good, meh)          #Well, at least this works

Я думаю, что эту ситуацию можно решить, если:

  1. fread может прочитать в bigz целых числах, или
  2. есть способизменить тип столбца без создания нового объекта.

По общему признанию, я data.table новичок.Заранее спасибо!

1 Ответ

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

Эти bigq числа кажутся трудными для работы.Кроме того, кажется, что их нельзя удерживать в качестве единственного столбца в data.table.

. Единственное, что я могу найти - это объявить новый data.table, что вы уже сделали, только он можетсделать более кратко, не создавая новый объект.

library(gmp)
library(data.table)

exa = as.bigz(2)^80          #A very large number          
cha = as.character(exa)
bad = data.table(nums = 1:3, lets = letters[1:3], bigs = rep(cha, 3))
bad = data.table(bad,bigsN = as.bigz(bad$bigs))
str(bad)

Однако эти столбцы не могут быть обработаны внутри data.table без тех же проблем.

bad$bigsN = bad$bigsN*2
## Error in `[<-.data.table`(x, j = name, value = value) : 
##   Unsupported type 'raw'
## In addition: Warning message:
## In `[<-.data.table`(x, j = name, value = value) :
##   Supplied 64 items to be assigned to 3 items of column 'bigsN' (61 unused)

Лучшее решение, которое я могудумать просто о том, чтобы сохранить эти объекты как отдельные векторы для вашего data.table.

as.list

Другим решением будет включение bigz в список.

library(gmp)
library(data.table)

exa = as.bigz(2)^80          #A very large number          
cha = as.character(exa)
bad = data.table(nums = 1:3, lets = letters[1:3], bigs = rep(cha, 3))
bad = bad[,bigs := as.list(as.bigz(bad$bigs))]

Это дает R лучшую возможность определять местоположение элементов и более эффективно использовать память на этапе создания.Обратной стороной является то, что каждый элемент имеет длину 1 bigz и, следовательно, содержит 4 избыточных байта данных на элемент.Это также все еще не может использоваться для арифметики векторизованным способом.

 bad$bigs = bad$bigs * 2
## Error in bad$bigs * 2 : non-numeric argument to binary operator
 bad$bigs[[2]] = bad$bigs[[2]] * 2
 bad$bigs
## [[1]]
## Big Integer ('bigz') :
## [1] 1208925819614629174706176
## 
## [[2]]
## Big Integer ('bigz') :
## [1] 2417851639229258349412352
## 
## [[3]]
## Big Integer ('bigz') :
## [1] 1208925819614629174706176

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

...