将data.table中的字符列转换为bigz Integer

我正在使用一个data.table,它已经从带有fread的.txt文件读入. data.table包含一些整数列以及一个非常大的整数列,我打算将其存储为bigz.但是,如果我打算保留所有的数字(和我这样做),fread只能读取大整数作为字符.

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

另外,我正在处理一个相当大的数据集.我的主要问题是将data.table中的字符列转换为bigz列而不创建新对象.

这是一个演示我的问题的玩具示例.首先,我知道data.tables可以有bigzcolumns – 如果它们是在一个新对象中引入的.

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?)

但是,如果要在运行中将字符列转换为bigz列,则会产生错误.这些转换方法中的语法“工作”w.r.t.如果as.bigz替换为as.character,则为数字nums列.

(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整数被存储为原始,虽然我不确定’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

我想如果以下情况可以解决这种情况:

> fread可以读取bigz整数,或者
>有一种方法可以在不创建新对象的情况下更改列类型.

不可否认,我是一名data.table新手.提前致谢!

最佳答案 这些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矢量.

点赞