2017-08-08 27 views
2

我想將火花數據幀中的NA/NULL分配給最近的鄰居。我來自R背景,所以我使用sparklyr,但無法找到一種方法來做到這一點。Sparklyr填充火花數據幀中的NA/NULL

下面是一個例子代碼:

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 

所以想填寫麻木柱,ID 1 NA至ID2麻木1,ID 5至任一ID 4和6(6或5),和ID 10到ID 9值(10)。它可以很容易地在R中完成。無論如何要通過Sparklyr在Spark中做到這一點?

這裏是我的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查詢和dplyr包中的mutate函數。它沒有解決連續行中多個NA值的情況,因爲它是您的基本R解決方案的翻譯,但它可能對其他(更完整的)方法有用。

我已經使用HiveQL的Lag and Lead函數來執行列向下移動和向上移動。它涉及創建一個新的輔助Spark表(example2),其中包含「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 

我希望這會有所幫助。

EDITED

如果你想避免使用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上打開了issue

+0

我認爲滯後和領導是最有幫助的!謝謝Jaime! –

+0

@KevinZheng不客氣:-) –