使用 sparklyr 在 R 中将字符串转换为逻辑字符串
Convert a string to logical in R with sparklyr
我在分布式文件系统中的许多 .csv 文件中存储了 1 亿行。我正在使用 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
When I attempt to convert the values to logical, the "<na>"
values are converted to 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
这与一致:
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
火花:
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
-> BooleanType
的 Spark 投射逻辑,其中:
- 字符串
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
转换引起的。请参阅 Improve Serialization on GitHub (credits to kevinykuo 以指出这一点)。
但是,如果您坚持使用基于 Spark 的逻辑,而不将数据提取到 R,一切应该都可以正常工作(例如,如果您将数据写入文件)。
I'm using spark_read_csv() to load the data
在那种情况下,您可以查看 CSV reader 的 nullValue
和 nanValue
options
。例如:
spark_read_csv(..., options=list(nullValue="<na>"))
或
spark_read_csv(..., options=list(nanValue="<na>"))
但请记住,NULL
/ NaN
的 Spark 语义与 R NA
/ NaN
.
不同
我在分布式文件系统中的许多 .csv 文件中存储了 1 亿行。我正在使用 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
When I attempt to convert the values to logical, the
"<na>"
values are converted toFALSE
令人惊讶的是没有。如果您进一步检查结果:
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
这与
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
火花
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
-> BooleanType
的 Spark 投射逻辑,其中:
- 字符串
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
转换引起的。请参阅 Improve Serialization on GitHub (credits to kevinykuo 以指出这一点)。
但是,如果您坚持使用基于 Spark 的逻辑,而不将数据提取到 R,一切应该都可以正常工作(例如,如果您将数据写入文件)。
I'm using spark_read_csv() to load the data
在那种情况下,您可以查看 CSV reader 的 nullValue
和 nanValue
options
。例如:
spark_read_csv(..., options=list(nullValue="<na>"))
或
spark_read_csv(..., options=list(nanValue="<na>"))
但请记住,NULL
/ NaN
的 Spark 语义与 R NA
/ NaN
.