2017-09-09 65 views
0

我正在尋找有關以下問題的幫助。 我有一個由五個級別組成的層次標識符的data.table。格式是[level_1]-[level_2]-[level_3].[level_4].[level_5](注意連字符分隔水平1,2和3與3,4和5之間的時間段)。我已經做出了比我的真實數據(它有6個級別)稍微小一點 - 我認爲這個解決方案的工作原理是一樣的。data.table:將row-wise粘貼功能應用於列表

一些玩具數據:

my_dt = setDT(data.frame("level_1" = c("H111", "H111", "H111", "H222", "H222", "H333"), "level_2" = c("a12", "a12", "b12", "c12", "c12", NA), 
        "level_3" = c("B9", "B2", "G1", NA, "F4", NA), 
        "level_4" = c("11", NA, "55", NA, "66", NA), 
        "level_5" = c("A", NA, "B", NA, NA, NA), 
        "key_level" = c(5,3,5,2,4,1))) 

舉例來說,當合並應該如下所示(如果正在報告說,他們在自己的「關鍵級」(或層次深度,如果你喜歡上面的標識符)。

full_key = c("H111-a12-B9.11.A", "H111-a12-B2", "H111-b12-G1.55.B", "H222-c12", "H222-c12-F4.66", "H333") 

我想一些幫助編寫一個函數,它所需的層級深度(hlevel),並報告關鍵就在特定深度(僅當key_level是> =的hlevel,否則返回NA)。

例如,如果我想報告上述3級的例子,我希望得到以下結果:

to_level_3 = c("H111-a12-B9", "H111-a12-B2", "H111-b12-G1", NA, "H222-c12-F4", NA) 

(正如你所看到的,有一個key_level所有行< 3應該是NA)。

我很努力讓這個工作。這是我的嘗試(可能比實際閱讀問題更困惑!)。此解決方案僅設置在分隔符是關鍵的開始,並沒有與key_level <比hlevel返回NA爲那些行...

get_level_x_key = function(dt, hlevel) 
{ 
     my_columns = paste0("level_", 1:4) 
     my_first_max = min(hlevel, 2) # first part of key is delimited with hypthens 
     my_dt[, 
      #do.call(paste, c(
       do.call(paste, c(.SD[key_level >= hlevel, my_columns[1:my_first_max], with = FALSE], list(sep="."))),] 
       #safe.ifelse(hlevel > 2, do.call(paste, c(.SD[, my_columns[2:hlevel], with = FALSE], list(sep="-"))), NA)), list(sep="-")] 
#)] 
} 

get_level_x_key(my_dt, 3) 
# Gives: [1] "H111-a12" "H111-a12" "H111-b12" "H222-c12" 

我已閱讀SO問題「」: paste two data.table columns,這讓我嘗試使用do.call - 但我不知道如何處理分隔符的變化或者如果key_level小於所需級別時如何返回NA。我曾想過,Reduce函數可能會有用......但我有點失落。

我會很感激任何指導,我有點卡住瞭如何打破這個問題。謝謝!

+0

難道你的意思是'setDT(my_df),子( 「[[:PUNCT:] NA *」, 「」,do.call(sprintf的,C( .SD,fmt =「%s-%s-%s。%s」))),.SDcols = level_1:level_4]' – akrun

+0

我覺得我讓我的例子太簡單了(你也是對的,我與我的分隔符使用不一致,對不起!)。將修復它。 – Meep

回答

1

也許試試這個:

weave = function(a, b) { 
    # return c(a[1], b[1], a[2], b[2], ..., a[N]) 
    stopifnot(length(b) >= length(a) - 1) 
    b = c(b[1:(length(a) - 1)], list(NULL)) 
    c(rbind(as.list(a), b)) 
} 

f = function(hlevel) { 
    my_dt[, ifelse(key_level < hlevel, 
        NA, 
        do.call(paste0, weave(.SD[, 1:hlevel], c('-','-','.','.'))))] 
} 

f(3) 
# [1] "H111-a12-B9" "H111-a12-B2" "H111-b12-G1" NA "H222-c12-F4" NA 

f(5) 
# [1] "H111-a12-B9.11.A" NA "H111-b12-G1.55.B" NA NA NA 
+0

太好了,謝謝:) – Meep