使用SparkR,如何将一个字符串列拆分成'n'个多列?

3
我正在使用SparkR 1.6,并且有一个包含数百万行的数据框。其中一个名为“categories”的列包含具有以下模式的字符串:
      categories
1 cat1,cat2,cat3
2      cat1,cat2
3     cat3, cat4
4           cat5

我想要将每个字符串分割,并创建“n”个新列,其中“n”是可能的类别数量(这里n = 5,但实际上可能超过50)。 每个新列将包含一个布尔值,表示类别的存在/不存在,例如:
   cat1  cat2  cat3  cat4  cat5
1  TRUE  TRUE  TRUE FALSE FALSE
2  TRUE  TRUE FALSE FALSE FALSE
3 FALSE FALSE  TRUE  TRUE FALSE
4 FALSE FALSE FALSE FALSE  TRUE

这如何仅使用sparkR api执行?谢谢您的时间。
祝好。
2个回答

3
让我们从导入和虚拟数据开始:
library(magrittr)

df <- createDataFrame(sqlContext, data.frame(
  categories=c("cat1,cat2,cat3", "cat1,cat2", "cat3,cat4", "cat5")
))

分割字符串:

separated <- selectExpr(df, "split(categories, ',') AS categories")

获取不同的分类:

categories <- select(separated, explode(separated$categories)) %>% 
  distinct() %>% 
  collect() %>%
  extract2(1)

构建表达式列表:

exprs <- lapply(
  categories, function(x) 
  alias(array_contains(separated$categories, x), x)
)

选择和检查结果

select(separated, exprs) %>% head()
##    cat1  cat2  cat3  cat4  cat5
## 1  TRUE  TRUE  TRUE FALSE FALSE
## 2  TRUE  TRUE FALSE FALSE FALSE
## 3 FALSE FALSE  TRUE  TRUE FALSE
## 4 FALSE FALSE FALSE FALSE  TRUE

谢谢 @zero323 的回答,但这有点过头了! - tsumit

0

这是一个纯Spark解决方案,不使用SparkR :: collect()。 如果给定的Spark数据框的列具有一定数量的分隔符,则以下是我的解决方案,并做出以下假设:

# separator = '::'
# number of separators = 3
# name of the respective column = col

首先,您需要使用拆分列创建输出数据框的模式:

AddFieldsToSchema = function(existingSchema, newFieldNames, newFieldTypes) {
  # This somewhat tortured syntax is necessary because the existingSchema
  # variable is actually a Java object under the hood
  existingNames = unlist(lapply(existingSchema$fields(), function(field) {
    field$name()
  }))
  existingTypes = unlist(lapply(existingSchema$fields(), function(field) {
    field$dataType.simpleString()
  }))
  
  combinedNames = c(existingNames, newFieldNames)
  combinedTypes = c(existingTypes, newFieldTypes)
  
  return(CreateSchema(combinedNames, combinedTypes))
}
num_separator = 3 
sdf_schema = SparkR::schema(sdf) %>%
              AddFieldsToSchema(paste0('col_', seq(1, num_separator)),
                                c(rep('string', num_separator)))

然后你需要一个用于给定列的拆分函数,该函数将在 SparkR::dapply 中使用:

my_func = function(x) {cbind(x, stringr::str_split_fixed(x$col, '::', 3))}

sdf_split = sdf %>% 
              SparkR::dapply(my_func, df_schema) 

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