2017-02-11 39 views
2

data.table提供了一個rleid函數,我發現它是非常有用的 - 當一個觀察變量發生變化時,它會作爲一個ticker,由一些其他變量排序。sparklyr中的遊程長度ID

library(dplyr) 


tbl = tibble(time = as.integer(c(1, 2, 3, 4, 5, 6, 7, 8)), 
      var = c("A", "A", "A", "B", "B", "A", "A", "A")) 

> tbl 
# A tibble: 8 × 2 
    time var 
    <int> <chr> 
1  1  A 
2  2  A 
3  3  A 
4  4  B 
5  5  B 
6  6  A 
7  7  A 
8  8  A 

期望的結果是

> tbl %>% mutate(rleid = data.table::rleid(var)) 
# A tibble: 8 × 3 
    time var rleid 
    <int> <chr> <int> 
1  1  A  1 
2  2  A  1 
3  3  A  1 
4  4  B  2 
5  5  B  2 
6  6  A  3 
7  7  A  3 
8  8  A  3 

我在想,如果我可以使用sparklyr提供的工具再現類似的東西。在進行測試時,我發現我能做的最好的事情就是達到我需要做出積極貢獻的程度,但卻無法實現這一點。

library(sparklyr) 

spark_install(version = "2.0.2") 
sc <- spark_connect(master = "local", 
        spark_home = spark_home_dir()) 


spk_tbl = copy_to(sc, tbl, overwrite = TRUE) 

spk_tbl %>% 
    mutate(var2 = (var != lag(var, 1L, order = time))) %>% # Thanks @JaimeCaffarel 
    mutate(var3 = if(var2) { paste0(time, var) } else { NA }) 

Source: query [8 x 4] 
Database: spark connection master=local[4] app=sparklyr local=TRUE 

    time var var2 var3 
    <int> <chr> <lgl> <chr> 
1  1  A TRUE 1A 
2  2  A FALSE <NA> 
3  3  A FALSE <NA> 
4  4  B TRUE 4B 
5  5  B FALSE <NA> 
6  6  A TRUE 6A 
7  7  A FALSE <NA> 
8  8  A FALSE <NA> 

我使用SparkR試過,但是我更喜歡sparklyr界面和易用性的,所以我非常能夠做到這一點星火SQL。

我當然可以通過將數據分割成足夠小的塊,然後運行一個函數並將其發回。

對於上下文來說,我發現rleid有用的原因是我使用了大量的火車數據,並且能夠對它的運行進行索引是非常有用的。

感謝所有幫助 AKHIL

+0

我想你可以使用這個:'TBL%> %mutate(rleid =(var!= lag(var,1,default =「asdf」)))%>%mutate(rleid = cumsum(rleid))'基本上這個解決方案:http://stackoverflow.com/a/33510765/2026277 –

+0

@JaimeCaffarel我沒有注意到'cumsum'整齊的做法...不幸的是'cumsum'似乎在Spark-SQL中不起作用(或者至少我不能使它工作)。 mutle(rleid = cumsum(rleid))%>% mutate(rleid = )' –

+0

OH!我錯了 - 我只需要先將布爾值轉換爲int。謝謝!考慮添加一個答案+我可以接受。再次感謝 –

回答

1

sparklyr一個工作的解決辦法是這樣的:

spk_tbl %>% 
    dplyr::arrange(time) %>% 
    dplyr::mutate(rleid = (var != lag(var, 1, order = time, default = FALSE))) %>% 
    dplyr::mutate(rleid = cumsum(as.numeric(rleid))) 
0

試試這個:

tbl %>% mutate(run = c(0,cumsum(var[-1L] != var[-length(var)]))) 
# A tibble: 8 × 3 
    time var run 
    <int> <chr> <dbl> 
1  1  A  0 
2  2  A  0 
3  3  A  0 
4  4  B  1 
5  5  B  1 
6  6  A  2 
7  7  A  2 
8  8  A  2 
+0

謝謝。只需指出,它仍然會受到spark sql中與原始評論答案中相同的投射問題的困擾。我也更喜歡'lead' /'lag' soln,因爲它強制確定性排序! –