2016-04-12 38 views
1

我有以下data.tableR:如何創建間接基於其他列的非靜態量條件列,在data.table

 Name x y h 120Hz 800Hz 1000Hz 1200Hz 
1: Tower1 1354 829 245  0  8  7  0 
2: Tower2 2654 234 285  7  0  3  0 
3: Tower3 822 3040 256  0  4  0  9 
4: Tower4 987 2747 250  0  6  5  3 
5: Tower5 1953 1739 301  0  0  8  2 

你可以用它創建

DT <- data.table(Name = c("Tower1", "Tower2", "Tower3", "Tower4", "Tower5"), 
       x = c(1354,2654,822,987,1953), 
       y = c(829,234,3040,2747,1739), 
       h = c(245,285,256,250,301), 
       `120Hz` = c(0,7,0,0,0), 
       `800Hz` = c(8,0,4,6,0), 
       `1000Hz` = c(7,3,0,5,8), 
       `1200Hz` = c(0,0,9,3,2)) 

實際上,它來自之前較大的data.table。最後四列是使用dcast從其他data.table自動生成的,因此無法事先知道列h後的列的數量或名稱。這個很重要。

的最終目標是創建一個名爲「範圍」另一列,每一行,其值列「H」之後,依賴於列中的值,因爲它遵循:

考慮頻率之間的以下關聯範圍。這些是唯一確定的關聯並且是靜態的,所以這些信息可以作爲預定義的data.table存儲。

assoc <- data.table(Frq = c("800Hz", "1000Hz", "1200Hz"), 
        Rng = c(750,850,950)) 

對於柱「H」後的四列中的每一個,該代碼應檢查列名assoc存在。如果是這樣,並且如果DT中該行所在行的該列中的值不爲零,則該代碼將考慮相應的Rng值(來自assoc)。在檢查所有四列後,代碼應該返回所考慮範圍的最大值並存儲在新列「範圍」中。


我的方法:

創建針對每個頻率列一個附配列:

DT <- DT[, paste0(colnames(DT)[5:ncol(DT)],'_r') := 0] 

然後,我可以使用條件的結構,確實上述算法。我們以列800Hz_r爲例。該列檢查800Hz列中的值。如果該值對於所討論的行不爲零,則返回750.最後,Range列僅取前4列中的最大值,以_f結尾。我被卡住的地方,我找不到一個有用的命令來這​​樣做。我試過的所有東西都會引發一些錯誤。

最後,輔助_f列應該被刪除。如果有人知道如何在不創建專業柱的情況下做到這一點,那就更好了。

這是(前輔助列刪除)預期的結果:

 Name x y h 120Hz 800Hz 1000Hz 1200Hz 120Hz_f 800Hz_f 1000Hz_f 1200Hz_f Range 
1: Tower1 1354 829 245  0  8  7  0  0  750  850  0 850 
2: Tower2 2654 234 285  7  0  3  0  0  0  850  0 850 
3: Tower3 822 3040 256  0  4  0  9  0  750  0  950 950 
4: Tower4 987 2747 250  0  6  5  3  0  750  850  950 950 
5: Tower5 1953 1739 301  0  0  8  2  0  0  850  950 950 

注:爲什麼有可能是因爲沒有出現在assoc命令頻率列的原因是因爲原始數據可能有錯別字。在這個例子中,列120Hz總是在120Hz_f列中只產生零,因此它不能被認爲是最大範圍。沒關係。

+1

合併b使用你的例子你能不能給我們預期產出? – DJJ

+0

例如,不清楚「範圍的最大值」是否對應於最大值assoc $ Rng或DT中的列。 – lmo

+0

@lmo以_f結尾的列中值的最大值。這些值來自assoc。我更新了問題,以便您可以看到想要的結果。 – JAR

回答

4

一個來回,以長格式可以使這項工作:

dcast(melt(DT, measure.vars=patterns("Hz$"))[assoc, on = c(variable = 'Frq') 
                , Rng := i.Rng * (value != 0)], 
     Name + x + y + h ~ variable, max, value.var='Rng')[, 
    do.call(function(...) pmax(..., na.rm = T), .SD), .SDcols = `120Hz`:`1200Hz`] 
#[1] 850 850 950 950 950 

或者你可以避開創建中間列,如果你遍歷assoc

DT[, Range := -Inf] 

assoc[, {DT[, Range := pmax(Range, (get(Frq) != 0) * Rng)]; NULL}, by = Frq] 

DT 
#  Name x y h 120Hz 800Hz 1000Hz 1200Hz Range 
#1: Tower1 1354 829 245  0  8  7  0 850 
#2: Tower2 2654 234 285  7  0  3  0 850 
#3: Tower3 822 3040 256  0  4  0  9 950 
#4: Tower4 987 2747 250  0  6  5  3 950 
#5: Tower5 1953 1739 301  0  0  8  2 950 
+0

第二種方法就是我想要的。像魅力一樣工作,非常感謝。只是一個小問題。我不熟悉這種結構,但顯然不是標準的變量賦值。我們可以做些什麼來避免控制檯輸出?我在談論'assoc [,{DT [,Range:= pmax(Range,(get(Frq)!= 0)* Rng)]; NULL},by = Frq]'顯示1個col的空data.table(0行):Frq' – JAR

+0

@JAR yep - 將其封裝在'invisible' – eddi

0

它不是完全按照你打算,但我的座右銘是當算法不適合數據,然後格式化數據到算法。

有點長,但很容易實現。

我用下面的代碼融化DT,並使用將Hz轉換爲數字,將「Hz」轉換爲數字。

a <- melt(DT,id.vars=1:4)[value>0][,crit:=as.numeric(gsub("Hz","",variable))] 

得到的東西,如:

##> a 
##  Name x y h variable value crit 
## 1: Tower1 1354 829 245 800Hz  8 800 
## 2: Tower1 1354 829 245 1000Hz  7 1000 
## 3: Tower2 2654 234 285 120Hz  7 120 
## 4: Tower2 2654 234 285 1000Hz  3 1000 
## 5: Tower3 822 3040 256 800Hz  4 800 
## 6: Tower3 822 3040 256 1200Hz  9 1200 
## 7: Tower4 987 2747 250 800Hz  6 800 
## 8: Tower4 987 2747 250 1000Hz  5 1000 
## 9: Tower4 987 2747 250 1200Hz  3 1200 
## 10: Tower5 1953 1739 301 1000Hz  8 1000 
## 11: Tower5 1953 1739 301 1200Hz  2 1200 

然後找到塔最大。

## > a[,.(crit=max(crit)),by=Name] 
## Name crit 
## 1: Tower1 1000 
## 2: Tower2 1000 
## 3: Tower3 1200 
## 4: Tower4 1200 
## 5: Tower5 1200 

然後用

b <- merge(setkey(a,Name,crit),setkey(a[,.(crit=max(crit)),by=Name],Name,crit)) 

把它合併要達到這樣的

## > b 
## Name crit x y h variable value 
## 1: Tower1 1000 1354 829 245 1000Hz  7 
## 2: Tower2 1000 2654 234 285 1000Hz  3 
## 3: Tower3 1200 822 3040 256 1200Hz  9 
## 4: Tower4 1200 987 2747 250 1200Hz  3 
## 5: Tower5 1200 1953 1739 301 1200Hz  2 

然後用assoc命令

## > merge(b,assoc,by.x="variable",by.y="Frq") 
## variable Name crit x y h value Rng 
## 1: 1000Hz Tower1 1000 1354 829 245  7 850 
## 2: 1000Hz Tower2 1000 2654 234 285  3 850 
## 3: 1200Hz Tower3 1200 822 3040 256  9 950 
## 4: 1200Hz Tower4 1200 987 2747 250  3 950 
## 5: 1200Hz Tower5 1200 1953 1739 301  2 950