Sparklyr заполняет NA/NULL в искровом фрейме
Я хотел бы назначить NA/NULL в кадре данных искры своему ближайшему соседу. Я пришел из R фона, поэтому я использую sparklyr, но не могу придумать, как это сделать.
Вот пример кода:
set.seed(1)
example <- data.frame (ID = 1:10, Cat = letters[1:5],
Numb = sample(c(NA, NA, NA, NA, 1:10), 10))
ID Cat Numb
1 1 a NA
2 2 b 1
3 3 c 3
4 4 d 6
5 5 e NA
6 6 a 5
7 7 b 4
8 8 c 9
9 9 d 10
10 10 e NA
Поэтому я хотел бы заполнить столбец Numb, ID 1 NA - ID2 Numb 1, ID 5 - либо ID 4 и 6 (6 или 5), а также значение ID 10 - ID 9 (10). Это можно сделать в R легко. Есть ли способ сделать это в Spark через Sparklyr?
Вот мое решение R:
example$Numb1 <- example$Numb[c(1,1:(nrow(example)-1))]
example$Numb2 <- example$Numb[c(2:(nrow(example)), nrow(example))]
example$Merge <- ifelse(is.na(example$Numb), ifelse(is.na(example$Numb1),
example$Numb2, example$Numb1), example$Numb)
ID Cat Numb Numb1 Numb2 Merge
1 1 a NA NA 1 1
2 2 b 1 NA 3 1
3 3 c 3 1 6 3
4 4 d 6 3 NA 6
5 5 e NA 6 5 6
6 6 a 5 NA 4 5
7 7 b 4 5 9 4
8 8 c 9 4 10 9
9 9 d 10 9 NA 10
10 10 e NA 10 NA 10
Конечно, все может стать более сложным, если у меня будет несколько значений NA в последовательных строках. Может быть, еще одно предложение можно посоветовать.
Но для sparklyr я понятия не имею, что я могу сделать.
1 ответ
Вот частично работающее решение с SQL-запросом и mutate
функция от dplyr
пакет. Он не затрагивает ситуацию множественных значений NA в последовательных строках, поскольку это перевод вашего базового решения R, но он может быть полезен для других (более полных) подходов.
Я использовал функции Lag и Lead в HiveQL, чтобы выполнить "сдвиг" вниз и вверх вашего столбца. Он включает в себя создание новой вспомогательной таблицы Spark (пример2), которая содержит столбцы "Numb1" и "Numb2". Затем, после создания вспомогательной таблицы, вы можете создать столбец "Объединенный" с mutate
library(DBI)
library(sparklyr)
library(dplyr)
set.seed(1)
exampleDF <- data.frame (ID = 1:10, Cat = letters[1:5],
Numb = sample(c(NA, NA, NA, NA, 1:10), 10))
# Connection to Spark and creation of the table to test.
sc <- spark_connect("local")
example <- copy_to(sc, exampleDF)
# Create a Spark table with columns Numb1 and Numb2
DBI::dbSendQuery(sc, "CREATE TABLE example2 AS (SELECT ID, Cat, Numb, LAG(Numb, 1) over (PARTITION BY 1 ORDER BY ID) AS Numb1,
LEAD(Numb, 1) over (PARTITION BY 1 ORDER BY ID) AS Numb2 FROM exampledf)")
# Load the auxiliary table as a Spark DataFrame
ex2 <- tbl(sc, "example2")
# Mutate in order to create the Merged column
res <- ex2 %>%
mutate(Merged = ifelse(is.na(Numb), ifelse(is.na(Numb1), Numb2, Numb1), Numb))
res
# Source: lazy query [?? x 6]
# Database: spark_connection
id cat numb numb1 numb2 Merged
<int> <chr> <int> <int> <int> <int>
1 1 a NA NA 1 1
2 2 b 1 NA 3 1
3 3 c 3 1 6 3
4 4 d 6 3 NA 6
5 5 e NA 6 5 6
6 6 a 5 NA 4 5
7 7 b 4 5 9 4
8 8 c 9 4 10 9
9 9 d 10 9 NA 10
10 10 e NA 10 NA 10
Как примечание, вы также можете избежать использования mutate
функция (и все ifelse
s) с помощью COALESCE
функция. Я думаю, что это будет намного эффективнее.
DBI::dbGetQuery(sc, "SELECT ID, Cat, Numb, COALESCE(Numb, Numb1, Numb2) AS Merged FROM example2")
ID Cat Numb Merged
1 1 a NA 1
2 2 b 1 1
3 3 c 3 3
4 4 d 6 6
5 5 e NA 6
6 6 a 5 5
7 7 b 4 4
8 8 c 9 9
9 9 d 10 10
10 10 e NA 10
Надеюсь, это поможет.
РЕДАКТИРОВАНИЕ
Если вы хотите вообще избежать использования SQL, вы можете сделать это также с dplyr
функции:
example %>% arrange(ID) %>%
mutate(Numb1 = lag(Numb, 1)) %>%
mutate(Numb2 = lead(Numb, 1L)) %>%
mutate(Merged = ifelse(is.na(Numb), ifelse(is.na(Numb1), Numb2, Numb1), Numb))
# Source: lazy query [?? x 6]
# Database: spark_connection
# Ordered by: ID
ID Cat Numb Numb1 Numb2 Merged
<int> <chr> <int> <int> <int> <int>
1 1 a NA NA 1 1
2 2 b 1 NA 3 1
3 3 c 3 1 6 3
4 4 d 6 3 NA 6
5 5 e NA 6 5 6
6 6 a 5 NA 4 5
7 7 b 4 5 9 4
8 8 c 9 4 10 9
9 9 d 10 9 NA 10
10 10 e NA 10 NA 10
# ... with more rows
У меня были некоторые проблемы с кодированием двух последовательных mutate
функции (вот почему я использовал смешанный подход SQL-dplyr в первую очередь). Я закончил тем, что открыл проблему на sparklyr.