从 Python 中的 R data.table 访问数据的推荐方法是什么?我可以避免将数据写入光盘吗?

ira*_*ira 11 python r data.table

是否有一些推荐的方法可以将数据从 R(以 形式data.table)传递到 Python,而无需将数据保存到磁盘?我知道我可以使用来自 R 的 python 模块使用reticulate(我想同样的事情可以在另一侧使用rpy2),但是从我读到的内容来看,这会损害库的整体性能,因此有很大的机会与尝试使用或使用 rpy2运行相比,最好将我的 r 存储到光盘data.table并使用 python 和运行从光盘读取相同的数据。lightgbmlightgbmreticulatedata.table

为什么我不坚持使用 R 或 Python

我更喜欢使用 r data.table(而不是Pandas)进行数据操作,因为它速度更快,内存效率更高,并且具有许多我喜欢的功能,例如不等连接、滚动连接、笛卡尔连接以及非常简单的融合和铸件。我也喜欢这样,每当我data.table在堆栈溢出中提出相关问题时,我都会很快得到高质量的答案,而Pandas我还没有那么成功。但是,有些任务我更喜欢 Python,例如梯度提升或神经网络。

jan*_*cki 7

没有推荐的方法。

理论上你必须将 R data.frame 转储到磁盘并在 python 中读取它。

在实践中(假设使用生产级操作系统),您可以使用“RAM 磁盘”位置,/dev/shm/这样您基本上将数据写入驻留在 RAM 内存中的文件,然后直接从 RAM 中读取,无需将数据转储到磁盘内存。

用法示例:

fwrite(iris, "/dev/shm/data.csv")
d = fread("/dev/shm/data.csv")
unlink("/dev/shm/data.csv")
Run Code Online (Sandbox Code Playgroud)

至于格式,您有以下选择:

  1. csv - 通用和便携格式

data.tablefwrite功能超快,并生成便携式 csv 数据文件。在多核机器上使用setDTthreads(0L)之前,请务必启用所有 cpu 线程fwrite

然后在 python 中你需要读取 csv 文件,pythondatatable模块会非常快,然后,如果需要,可以使用x.to_pandas().

  1. feather - “便携式”二进制格式

另一种选择是使用 R 的arrowpackage 和 function write_feather,然后使用pyarrowmodule 和read_feather.

在大多数情况下,这种格式应该比 csv 更快,请参阅下面的时间安排。在写入数据的情况下,差异可能不会那么大,但在大多数情况下读取数据会快得多,尤其是在 R 中读取许多字符变量时(尽管这不是您的用例,因为您在 python 中读取)。另一方面,它还不是真正可移植的(请参阅apache/arrow#8732)。此外,最终如果发布新版本3,那么使用当前羽毛保存的文件可能不再兼容。

  1. fst - 快速二进制格式

fst可以用作羽毛格式的更快替代方案,但尚无法在 python 中读取 fst 数据,因此目前无法应用此方法来解决您的问题。您可以在https://github.com/fstpackage/fst/issues/184 中跟踪此 FR 的进度,当问题得到解决时,它可能会以最快的方式解决您的问题。


使用以下脚本

library(data.table)
setDTthreads(0L) ## 40

N = 1e8L
x = setDT(lapply(1:10, function(...) sample.int(N)))
system.time(arrow::write_feather(x, "/dev/shm/data.feather"))
system.time(fwrite(x, "/dev/shm/data.csv", showProgress=FALSE))
rm(x)
## run python

unlink(paste0("/dev/shm/data.",c("csv","feather")))
N = 1e8L
x = setDT(lapply(1:10, function(...) runif(N)))
system.time(arrow::write_feather(x, "/dev/shm/data.feather"))
system.time(fwrite(x, "/dev/shm/data.csv", showProgress=FALSE))
rm(x)
## run python

unlink(paste0("/dev/shm/data.",c("csv","feather")))
N = 1e7L
x = setDT(lapply(1:10, function(...) paste0("id",sample.int(N))))
system.time(arrow::write_feather(x, "/dev/shm/data.feather"))
system.time(fwrite(x, "/dev/shm/data.csv", showProgress=FALSE))
rm(x)
## run python

unlink(paste0("/dev/shm/data.",c("csv","feather")))
Run Code Online (Sandbox Code Playgroud)
import datatable as dt
import timeit
import gc
from pyarrow import feather

gc.collect()
t_start = timeit.default_timer()
x = dt.fread("/dev/shm/data.csv")
print(timeit.default_timer() - t_start, flush=True)
gc.collect()
t_start = timeit.default_timer()
y = x.to_pandas()
print(timeit.default_timer() - t_start, flush=True)
del x, y

gc.collect()
t_start = timeit.default_timer()
x = feather.read_feather("/dev/shm/data.feather", memory_map=False)
print(timeit.default_timer() - t_start, flush=True)
del x
Run Code Online (Sandbox Code Playgroud)

我得到以下时间:

  • 整数:
    • 写:feather 2.7s vs csv 5.7s
    • 阅读:feather 2.8s vs csv 111s+3s
  • 双倍的:
    • 写:feather 5.7s vs csv 10.8s
    • 阅读:feather 5.1s vs csv 180s+4.9s
  • 特点:
    • 写:feather 50.2s vs csv 2.8s
    • 阅读:feather 35s vs csv 14s+16s

基于所提供的数据案例(整数/双精度为 1e8 行,字符为 1e7 行;10 列:整数/双精度/字符),我们可以得出以下结论:

  • 写入 int 和 double 对 csv 来说比羽毛慢大约 2 倍
  • csv 写入字符比羽毛快 20 倍左右
  • csv 读取 int 和 double 比羽毛慢得多
  • 从 python 数据表到 Pandas 的 int 和 double 转换相对便宜
  • csv 的读取字符比羽毛快 2 倍左右
  • 从python数据表到pandas的转换字符很昂贵

请注意,这些是非常基本的数据案例,请务必检查实际数据的时间。