r - 根据列数据类型对 Spark 数据框(在 Sparklyr 中)进行子集化的最佳方法是什么

标签 r apache-spark machine-learning data-science sparklyr

我正在将一堆列转换为虚拟变量。我想从数据框中删除原始分类变量。我正在努力弄清楚如何在 Sparklyr 中做到这一点。在 dplyr 中很简单,但 dplyr 功能在 Sparklyr 中不起作用。

例如:

首先创建一个 Spark 数据框:

    ###create dummy data to figure out how model matrix formulas work in sparklyr
v1 <- sample( LETTERS[1:4], 50000, replace=TRUE, prob=c(0.1, 0.2, 0.65, 0.05))
v2 <- sample( LETTERS[5:6], 50000, replace=TRUE, prob=c(0.7,0.3))
v3 <- sample( LETTERS[7:10], 50000, replace=TRUE, prob=c(0.3, 0.2, 0.4, 0.1))
v4 <- sample( LETTERS[11:15], 50000, replace=TRUE, prob=c(0.1, 0.1, 0.3, 0.05,.45))
v5 <- sample( LETTERS[16:17], 50000, replace=TRUE, prob=c(0.4,0.6))
v6 <- sample( LETTERS[18:21], 50000, replace=TRUE, prob=c(0.1, 0.1, 0.65, 0.15))
v7 <- sample( LETTERS[22:26], 50000, replace=TRUE, prob=c(0.1, 0.2, 0.65, 0.03,.02))
v8 <- rnorm(n=50000,mean=.5,sd=.1)
v9 <- rnorm(n=50000,mean=5,sd=3)
v10 <- rnorm(n=50000,mean=3,sd=.5)
response <- rnorm(n=50000,mean=10,sd=2)

dat <- data.frame(v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,response)
write.csv(dat,file='fake_dat.csv',row.names = FALSE)

#push "fake_dat" to the hdfs

library(dplyr)
library(sparklyr)
#configure the spark session and connect
config <- spark_config()
config$`sparklyr.shell.driver-memory` <- "2G" #change depending on the size of the data
config$`sparklyr.shell.executor-memory` <- "2G"

# sc <-  spark_connect(master='local', spark_home='/usr/hdp/2.5.0.0-1245/spark',config = config)
# sc

sc <-  spark_connect(master='yarn-client', spark_home='/usr/hdp/2.5.0.0-1245/spark',config = config)
sc

#can also set spark_home as '/usr/hdp/current/spark-client'

#read in the data from the hdfs
df <- spark_read_csv(sc,name='fdat',path='hdfs://pnhadoop/user/stc004/fake_dat.csv')

#create spark table
dat <- tbl(sc,'fdat')

现在创建虚拟变量:

for(i in 1:7){
  dat <- ml_create_dummy_variables(x=dat,colnames(dat)[i], reference = NULL)
}

我可以简单地使用

删除原始分类变量
drop.cols <- colnames(dat)[1:7]
dat1 <-
  dat %>%
  select(-one_of(drop.cols))

但是,我实际使用的数据有 300 个分类变量。我需要一种快速方法来识别哪些列是字符/因子。将这些列转换为虚拟变量后 - 我可以删除原始的分类变量。我尝试过以下方法:

test <-
  dat %>%
  select_if(is.character)

然后我收到以下错误:

Error: Selection with predicate currently require local sources

我也尝试过:

cls <- sapply(dat, class)
cls

但我得到:

> cls

         src         ops
    [1,] "src_spark" "op_base_remote"
    [2,] "src_sql"   "op_base"
    [3,] "src"       "op"

关于如何做到这一点有什么想法吗?

最佳答案

称其为“最好的”有点夸张,但您可以尝试这样的方法(为方便起见,使用 purr):

columns_for_type <- function(sc, name, type="StringType") {
  spark_session(sc) %>% 
    invoke("table", name) %>% 
    # Get (name, type) tuples
    invoke("dtypes") %>%
    # Filter by type
    purrr::keep(function(x) invoke(x, "_2") == type) %>% 
    purrr::map(function(x) invoke(x, "_1"))
}

可以按如下方式使用:

library(sparklyr)
library(dplyr)

sc <- spark_connect(master = "local[*]")
iris_tbl <- copy_to(sc, iris, name="iris", overwrite=TRUE)

columns_for_type(sc, "iris", "StringType")
[[1]]
[1] "Species"
columns_for_type(sc, "iris", "DoubleType")
[[1]]
[1] "Sepal_Length"

[[2]]
[1] "Sepal_Width"

[[3]]
[1] "Petal_Length"

[[4]]
[1] "Petal_Width"

结果可以传递给select_:

iris_tbl %>% select_(.dots=columns_for_type(sc, "iris", "StringType"))
Source:   query [150 x 1]
Database: spark connection master=local[8] app=sparklyr local=TRUE

   Species
     <chr>
1   setosa
2   setosa
3   setosa
4   setosa
5   setosa
6   setosa
7   setosa
8   setosa
9   setosa
10  setosa
# ... with 140 more rows

您可以使用类似的方法,将一行作为 data.frame:

iris_tbl %>% head(n=1) %>% as.data.frame %>% lapply(class)

但它需要额外的 Spark 操作。

关于r - 根据列数据类型对 Spark 数据框(在 Sparklyr 中)进行子集化的最佳方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42720876/

相关文章:

r - 将多个ggplots打印到一个pdf中,每页多个图

r - 将边列表加权到 r 中的有向和无向图中

scala - 在 Zeppelin 中指定与分类器的依赖关系

python - XGBoost feature_importances_ 参数返回 nan

machine-learning - 减少错误预测类别的权重

R 传单 Shiny : shape_click$id is NULL

r - 使用 ggplot 固定填充密度图的不同部分

apache-spark - spark 中的 RDD 内存占用

apache-spark - 运行 Spark MLlib kmeans 时出现 OutOfMemory

machine-learning - 如何识别文档类别,例如电影或传记