使用 sparklyr 在 R 中将字符串转换为逻辑字符串

Posted

技术标签:

【中文标题】使用 sparklyr 在 R 中将字符串转换为逻辑字符串【英文标题】:Convert a string to logical in R with sparklyr 【发布时间】:2018-05-12 09:18:45 【问题描述】:

我有 1 亿行存储在分布式文件系统的许多 .csv 文件中。我正在使用 spark_read_csv() 毫无问题地加载数据。我的许多列都存储为字符逻辑值:"true""false""<na>"。我无法控制这个。

当我尝试将值转换为逻辑值时,"<na>" 值将转换为带有"false" 值的FALSE。关于如何克服这个问题的任何想法?

test_lgl <- 
  tibble(a = c(TRUE, TRUE, NA, NA, FALSE, FALSE),
         b = c("true", "true", "na", "<na>", "false", "f"))

test_lgl %>% mutate_if(is.character, as.logical)

# this works
   a     b
  <lgl> <lgl>
1  TRUE  TRUE
2  TRUE  TRUE
3    NA    NA
4    NA    NA
5 FALSE FALSE
6 FALSE    NA

sc <- spark_connect(master = "local")
spark_lgl <- copy_to(sc, test_lgl)

spark_lgl %>% mutate_if(is.character, as.logical)

# this does not
      a     b
  <lgl> <lgl>
1  TRUE  TRUE
2  TRUE  TRUE
3 FALSE FALSE
4 FALSE FALSE
5 FALSE FALSE
6 FALSE FALSE

【问题讨论】:

不直接相关但... github.com/rstudio/sparklyr/issues/127 【参考方案1】:

当我尝试将值转换为逻辑值时,"&lt;na&gt;" 值将转换为 FALSE

令人惊讶的是没有。如果您进一步检查结果:

spark_lgl_boolean <- spark_lgl %>% mutate_if(is.character, as.logical)
spark_lgl_boolean %>% mutate_all(is.na)

Applying predicate on the first 100 rows
# Source:   lazy query [?? x 2]
# Database: spark_connection
      a     b
  <lgl> <lgl>
1 FALSE FALSE
2 FALSE FALSE
3  TRUE  TRUE
4  TRUE  TRUE
5 FALSE FALSE
6 FALSE FALSE

这与NA count一致:

spark_lgl_boolean %>%
  mutate_all(is.na) %>% 
  mutate_all(as.numeric) %>%
  summarize_all(sum)
# Source:   lazy query [?? x 2]
# Database: spark_connection
      a     b
  <dbl> <dbl>
1     2     2

火花execution plan:

spark_lgl %>% mutate_if(is.character, as.logical) %>% optimizedPlan
Applying predicate on the first 100 rows
<jobj[1074]>
  org.apache.spark.sql.catalyst.plans.logical.Project
  Project [a#10, cast(b#11 as boolean) AS b#2037]
+- InMemoryRelation [a#10, b#11], true, 10000, StorageLevel(disk, memory, deserialized, 1 replicas), `test_lgl`
      +- *FileScan csv [a#10,b#11] Batched: false, Format: CSV, Location: InMemoryFileIndex[file:/tmp/..., PartitionFilters: [], PushedFilters: [], ReadSchema: struct<a:boolean,b:string>

StringType 的 Spark 转换逻辑 -> BooleanType 其中:

字符串 TRUE / T(不区分大小写)和 1 被转换为 true 文字。 字符串 FALSE / F(不区分大小写)和 0 被转换为 false 文字。 上面不匹配的字符串被转换为NULL (~NA)。
scala> Seq("tRUE", "FALSE", "f", "<na>", "NA", "1", "0").toDF("x").select($"x".cast("boolean")).show
+-----+
|    x|
+-----+
| true|
|false|
|false|
| null|
| null|
| true|
|false|
+-----+

问题似乎是由sparklyr 转换专门引入的。请参阅 GitHub 上的 Improve Serialization(感谢 kevinykuo 指出这一点)。

但是,如果您坚持使用基于 Spark 的逻辑,而不将数据提取到 R,那么事情应该可以正常工作(例如,如果您将数据写入文件)。

我正在使用 spark_read_csv() 来加载数据

在这种情况下,您可以查看CSV reader 中的nullValuenanValue options。例如:

spark_read_csv(..., options=list(nullValue="<na>"))

spark_read_csv(..., options=list(nanValue="<na>"))

但请记住,NULL / NaN 的 Spark 语义与 R NA / NaN 不同。

【讨论】:

以上是关于使用 sparklyr 在 R 中将字符串转换为逻辑字符串的主要内容,如果未能解决你的问题,请参考以下文章

在 sparklyr 中将 12 小时制转换为 24 小时制

在R中将字符串转换为二进制向量

如何在R中使用sparklyr打开“GZ FILE”?

如何在 Sparklyr 中正确使用特征转换函数

R - 如何使用 sparklyr 复制火花数据框中的行

在R中创建一个函数,在整个数据帧中将字符串转换为整数