2014-06-20 33 views
0

下面是生成數據以演示問題的代碼。R將代碼應用於不同的因素或級別

con <- textConnection(' 
    Nu Na Vo 
100 A 60 
103 A 2 
104 A 2 
106 A 5 
107 A 1 
108 A 1 
112 A 50 
100 B 1 
108 B 4 
109 B 2 
120 B 30 
109 C 40 
         ') 
tt <- read.table(con, header = T) 
close(con) 
test <- as.data.frame(tt) 

我有以下代碼。將值指定給「Sta」列,並將該值與i + 1行之間的「Nu」的差值添加到「滯後」列中。

library(dplyr) 
# to sort "Na" column and arrange "Nu" in descending order 
# in order to apply the code below. 
test2 <- tt %.% arrange(Na, -Nu) 
for (i in 1:nrow(test2)) { 

    if (i < nrow(test2)) { 

    if (test2[i, ]$Nu - 2 > test2[i+1, ]$Nu) { 
     test2[i, 4] <- "N" 
     test2[i, 5] <- test2[i, ]$Nu - test2[i+1, ]$Nu 
    } else if (test2[i, ]$Nu - 2 <= test2[i+1, ]$Nu) { 
     test2[i, 4] <- "Y" 
     test2[i, 5] <- test2[i, ]$Nu - test2[i+1, ]$Nu 
    } 

    } else if (i == nrow(test2)) { 
    test2[i, 4] <- "N" 
    test2[i, 5] <- 0 
    } 
} 
names(test2)[names(test2) == "V4"] <- "Sta" 
names(test2)[names(test2) == "V5"] <- "Lag" 
test2 

運行代碼後,它會產生如下的結果:

Nu Na Vo Sta Lag 
1 112 A 50 N 4 
2 108 A 1 Y 1 
3 107 A 1 Y 1 
4 106 A 5 Y 2 
5 104 A 2 Y 1 
6 103 A 2 N 3 
7 100 A 60 Y -20 
8 120 B 30 N 11 
9 109 B 2 Y 1 
10 108 B 4 N 8 
11 100 B 1 Y -9 
12 109 C 40 N 0 

下「STA」列中的值正確分配而不是爲「延遲」列。原意是根據「Na」中不同的值/等級應用代碼,即「A」,「B」,「C」。不要如何將代碼分別應用於「A」,「B」,「C」並將單獨的結果合併到一個表中。理想的結果應該是:

Nu Na Vo Sta Lag 
1 112 A 50 N 4 
2 108 A 1 Y 1 
3 107 A 1 Y 1 
4 106 A 5 Y 2 
5 104 A 2 Y 1 
6 103 A 2 N 3 
7 100 A 60 Y 0 << Last row for "A". "Lag" should be "0"; "Sta" should be "N". 
8 120 B 30 N 11 
9 109 B 2 Y 1 
10 108 B 4 N 8 
11 100 B 1 Y 0 << Last row for "B". "Lag" should be "0"; "Sta" should be "N". 
12 109 C 40 N 0 << Last row for "C". "Lag" should be "0"; "Sta" should be "N". 

編輯

不知道如何將代碼應用到「娜」的不同因素/級別:「A」,「B」和「C」。可以使用split()或應用函數族?從上面代碼的結果和意圖可以看出,結果應該是FACTOR/LEVEL/Element依賴(希望我使用的是正確的術語),並且會影響「Sta」和「Lag」列下的值。然而我的代碼無法區分這一點。感謝您提供的任何幫助。謝謝

一個不雅的解決方案!

爲了保持完整性,我特此發佈一個可能的解決方案。我用艱難的方式編碼。如果有人能幫助簡化它,那將非常感激。

con <- textConnection(' 
    Nu Na Vo 
100 A 60 
103 A 2 
104 A 2 
106 A 5 
107 A 1 
108 A 1 
112 A 50 
100 B 1 
108 B 4 
109 B 2 
120 B 30 
109 C 40 
         ') 
tt <- read.table(con, header = T) 
close(con) 
require(dplyr); require(data.table) 
test2 <- tt %.% arrange(Na, -Nu) 
spl <- split(test2, test2$Na) 
spl 
for (i in 1:length(levels(test2$Na))) { 
    for (j in 1:nrow(spl[[i]])) { 

    if (j < nrow(spl[[i]])) { 

     if (spl[[i]][j, ]$Nu - 2 > spl[[i]][j+1, ]$Nu) { 
     spl[[i]][j, 4] <- "N" 
     spl[[i]][j, 5] <- spl[[i]][j, ]$Nu - spl[[i]][j+1, ]$Nu 
     } else if (spl[[i]][j, ]$Nu - 2 <= spl[[i]][j+1, ]$Nu) { 
     spl[[i]][j, 4] <- "Y" 
     spl[[i]][j, 5] <- spl[[i]][j, ]$Nu - spl[[i]][j+1, ]$Nu 
     } 
    } else if (j == nrow(spl[[i]])) { 
     spl[[i]][j, 4] <- "N" 
     spl[[i]][j, 5] <- 0 
    } 
    } 
} 
spl <- rbindlist(spl) 
setnames(spl, c("V4", "V5"), c("Sta", "Lag")) 
spl 

回答

0

ave救援 - 如果使用兩次,這將基本上做同樣的比較,爲你的長期循環代碼。

首先,使用每個組的diff來計算滯後差異,並將每個組中最後一行的值設置爲0.然後使用計算出的滯後值確定「Sta」列,強制每個組中的最後一行組的值被分配「N」。根據要求

test2$Lag <- with(test2, ave(Nu, Na, FUN=function(x) -c(diff(x),0))) 
test2$Sta <- with(test2, ave(Lag, Na, FUN=function(x) { 
      out <- ifelse(x > 2, "N", "Y"); out[length(out)] <- "N"; out})) 

相同的結果:

test2[c(1:3,5,4)] 

# Nu Na Vo Sta Lag 
#1 112 A 50 N 4 
#2 108 A 1 Y 1 
#3 107 A 1 Y 1 
#4 106 A 5 Y 2 
#5 104 A 2 Y 1 
#6 103 A 2 N 3 
#7 100 A 60 N 0 
#8 120 B 30 N 11 
#9 109 B 2 Y 1 
#10 108 B 4 N 8 
#11 100 B 1 N 0 
#12 109 C 40 N 0 
+0

感謝。看起來這是一種快速而骯髒的方式:-)想知道如何利用列「Na」下的因子或等級屬性。如果有一個可以合併到原始代碼體內的腳本會很好。可以使用split(),lapply()等? – KFB

+0

'ave'在內部使用分割。輸入'ave'並在R控制檯中輸入以查看它使用的代碼。請注意,'Na'是'ave'調用的第二個參數,它是傳遞給split的'factor'。 – thelatemail

+0

對,但無法使用實際爲其編寫腳本的部分代碼:
'} else if(i == nrow(test2)){ test2 [i,4] < - 「N」 test2 [i,5] < - 0 }' – KFB

相關問題