首页 文章

Sparklyr在spark数据帧中填充NA / NULL

提问于
浏览
2

我想将火花数据帧中的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中轻松完成 . 无论如何,通过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值,事情会变得更复杂 . 也许可以建议另一个建议 .

但对于闪闪发光的人来说,我不知道我能做些什么 .

1 回答

  • 1

    这是一个部分工作的解决方案,带有SQL查询和 dplyr 包中的 mutate 函数 . 它没有解决连续行中多个NA值的情况,因为它是基本R解决方案的转换,但它可能对其他(更完整)方法有用 .

    我已经使用了HiveQL的Lag and Lead函数来执行列的"shifting"向上和向下 . 它涉及创建一个新的辅助Spark表(example2),它保存"Numb1"和"Numb2"列 . 然后,一旦创建了辅助表,就可以使用 mutate 创建"Merged"列

    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
    

    作为旁注,您还可以通过 COALESCE 函数避免使用 mutate 函数(以及所有 ifelse ) . 我认为这会更有效率 .

    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 .

相关问题