如何在R中读取Parquet文件并将其转换为R DataFrame?

65

我希望能够用R编程语言处理Apache Parquet文件(在我的情况下,这些文件是由Spark生成的)。

是否有可用的R读取器?或者正在开发中吗?

如果没有,最快的方法是什么?注意:有Java和C++绑定:https://github.com/apache/parquet-mr

10个回答

43

最简单的方法是使用这个 arrow 软件包,它可以在 CRAN上找到

install.packages("arrow")
library(arrow)
read_parquet("somefile.parquet")

以前可以通过Python使用pyarrow来完成这个任务,但现在R也打包了这个功能,无需使用Python。

如果您不想从CRAN安装,可以直接构建或从GitHub安装:

git clone https://github.com/apache/arrow.git
cd arrow/cpp && mkdir release && cd release

# It is important to statically link to boost libraries
cmake .. -DARROW_PARQUET=ON -DCMAKE_BUILD_TYPE=Release -DARROW_BOOST_USE_SHARED:BOOL=Off
make install

然后您可以安装 R arrow 包:

devtools::install_github("apache/arrow/r")

并使用它来加载Parquet文件

library(arrow)
#> 
#> Attaching package: 'arrow'
#> The following object is masked from 'package:utils':
#> 
#>     timestamp
#> The following objects are masked from 'package:base':
#> 
#>     array, table
read_parquet("somefile.parquet", as_tibble = TRUE)
#> # A tibble: 10 x 2
#>        x       y
#>    <int>   <dbl>
#> …

11
最近{arrow}已经登陆CRAN了:https://cran.r-project.org/web/packages/arrow/index.html - krlmlr
或者,通过conda使用conda install r-arrow安装。 - Keith Hughitt

38
你可以简单地使用 arrow 包
install.packages("arrow")
library(arrow)
read_parquet("myfile.parquet")

1
@DavidArenburg 确实如此,不过这个回答反映了 arrow 现在已经可以在 CRAN 上直接安装的变化。 - B.Liu

30

如果你正在使用Spark,随着Spark 1.4的发布,这现在相对简单了。请参阅下面的示例代码,该代码使用了现在已成为Apache Spark核心框架一部分的SparkR软件包。

# install the SparkR package
devtools::install_github('apache/spark', ref='master', subdir='R/pkg')

# load the SparkR package
library('SparkR')

# initialize sparkContext which starts a new Spark session
sc <- sparkR.init(master="local")

# initialize sqlContext
sq <- sparkRSQL.init(sc)

# load parquet file into a Spark data frame and coerce into R data frame
df <- collect(parquetFile(sq, "/path/to/filename"))

# terminate Spark session
sparkR.stop()

扩展示例可在https://gist.github.com/andyjudson/6aeff07bbe7e65edc665上查看。

如果您不使用Spark,我不知道还有哪个软件包可供使用。


你有什么猜测为什么这个代码不能在S3上使用我的Parquet文件?密钥和密码已经声明,而且Python可以通过sqlCtx.read.parquet("s3n://bucket/path/part1=whatever/")正常读取它们。我也尝试将密钥和密码直接放在URL中 - "s3n://key:pass@bucket/path"。 - Ben Hunter
恐怕我没有使用过S3,所以不确定哪些功能可用。可能SparkR尚未支持S3,我们只是在核心中看到了第一个版本,并且确实会遇到问题。您是否确认从pyspark / scala会话加载数据?-如果是这样,我更倾向于上述理论。值得检查SparkR问题日志(https://issues.apache.org/jira/browse/SPARK/component/12325400/?selectedTab=com.atlassian.jira.jira-projects-plugin:component-summary-panel),或者尝试搜索与S3相关的问题? - Andy Judson
尝试在文件中定义AWS环境变量或在启动RStudio时定义: 我更喜欢使用自包含脚本(第一种选项) Sys.setenv(AWS_ACCESS_KEY_ID =“”) Sys.setenv(AWS_SECRET_ACCESS_KEY =“”) - seufagner
使用这个会出现两个警告 -- "parquetFile(sqlContext...)已经被弃用。请使用parquetFile(...)代替。" --和-- "f'已经被弃用。请使用read.parquet代替。" 不幸的是,parquetFileread.parquet`都没有文档记录,因此现在实现的正确语法不清楚。 - MichaelChirico

16

如果您不想使用 SparkR,现在可以尝试使用sparklyr:

# install.packages("sparklyr")
library(sparklyr)

sc <- spark_connect(master = "local")

spark_tbl_handle <- spark_read_parquet(sc, "tbl_name_in_spark", "/path/to/parquetdir")

regular_df <- collect(spark_tbl_handle)

spark_disconnect(sc)

为了使用collect包,需要安装dplyr:install.packages("dplyr") - nessa.gp

6

使用reticulate,您可以从Python中使用pandas访问parquet文件。这样可以避免运行Spark实例的麻烦。

library(reticulate)
library(dplyr)
pandas <- import("pandas")
read_parquet <- function(path, columns = NULL) {

  path <- path.expand(path)
  path <- normalizePath(path)

  if (!is.null(columns)) columns = as.list(columns)

  xdf <- pandas$read_parquet(path, columns = columns)

  xdf <- as.data.frame(xdf, stringsAsFactors = FALSE)

  dplyr::tbl_df(xdf)

}

read_parquet(PATH_TO_PARQUET_FILE)

1
我觉得这不应该被选为答案,因为下面有本地的 R 方法。 - Kermit
1
老实说,在我看来:下面的答案需要使用Spark,而它并不是R语言的本地库。如有错误请指正。 - Jonathan
在我看来,这是一个有效的答案,有时甚至可能是“最佳”答案。然而,在大多数情况下,其他解决方案将会更好。 - Nzbuu

4

Spark已经更新,有许多新的东西和功能被弃用或重命名。

Andy在上面的答案适用于Spark v.1.4,但在Spark v.2.3上,这是适用于我的更新。

  1. Download latest version of apache spark https://spark.apache.org/downloads.html (point 3 in the link)

  2. extract the .tgz file.

  3. install devtool package in rstudio

    install.packages('devtools')
    
  4. Open terminal and follow these steps

    # This is the folder of extracted spark `.tgz` of point 1 above
    export SPARK_HOME=extracted-spark-folder-path 
    cd $SPARK_HOME/R/lib/SparkR/
    R -e "devtools::install('.')"
    
  5. Go back to rstudio

    # load the SparkR package
    library(SparkR)
    
    # initialize sparkSession which starts a new Spark session
    sc <- sparkR.session(master="local")
    
    # load parquet file into a Spark data frame and coerce into R data frame
    df <- collect(read.parquet('.parquet-file-path'))
    
    # terminate Spark session
    sparkR.stop()
    

3

miniparquet 是一个新的专用软件包。使用以下命令进行安装:

devtools::install_github("hannesmuehleisen/miniparquet")

以下是来自文档的示例:

library(miniparquet)

f <- system.file("extdata/userdata1.parquet", package="miniparquet")
df <- parquet_read(f)
str(df)

# 'data.frame': 1000 obs. of  13 variables:
#  $ registration_dttm: POSIXct, format: "2016-02-03 07:55:29" "2016-02-03 17:04:03" "2016-02-03 01:09:31" ...
#  $ id               : int  1 2 3 4 5 6 7 8 9 10 ...
#  $ first_name       : chr  "Amanda" "Albert" "Evelyn" "Denise" ...
#  $ last_name        : chr  "Jordan" "Freeman" "Morgan" "Riley" ...
#  $ email            : chr  "ajordan0@com.com" "afreeman1@is.gd" "emorgan2@altervista.org" "driley3@gmpg.org" ...
#  $ gender           : chr  "Female" "Male" "Female" "Female" ...
#  $ ip_address       : chr  "1.197.201.2" "218.111.175.34" "7.161.136.94" "140.35.109.83" ...
#  $ cc               : chr  "6759521864920116" "" "6767119071901597" "3576031598965625" ...
#  $ country          : chr  "Indonesia" "Canada" "Russia" "China" ...
#  $ birthdate        : chr  "3/8/1971" "1/16/1968" "2/1/1960" "4/8/1997" ...
#  $ salary           : num  49757 150280 144973 90263 NA ...
#  $ title            : chr  "Internal Auditor" "Accountant IV" "Structural Engineer" "Senior Cost Accountant" ...
#  $ comments         : chr  "1E+02" "" "" "" ...

1

如果要读取Amazon S3存储桶中的Parquet文件,请尝试使用s3a而不是s3n。当我使用EMR 1.4.0、RStudio和Spark 1.5.0读取Parquet文件时,这对我很有效。


1
如果您有多个Parquet文件,您可能需要执行以下操作:
data.table::rbindlist(lapply(Sys.glob("path_to_parquet/part-*.parquet"), arrow::read_parquet))

我编写了一个R包来完成这个任务。https://github.com/jhnwllr/parqr - John Waller

1

最近我发布了一个R包来读取parquet和delta文件。它基本上使用arrow包,但是可以在本地和云中处理delta文件。

你可以像这样使用:

 readparquetR(pathtoread="C:/users/...",format="delta")# format can be parquet or delta

如果您想直接从Azure上读取数据,这个方法应该可以。
 readparquetR(pathtoread="blobpath/subdirectory/",    filelocation = "azure",    format="delta",    containerconnection = your_connection) 

欢迎自由使用或贡献 https://github.com/mkparkin/Rinvent


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接