2012-02-23 65 views
3

我一直在考慮這一點,並且無法提出解決方案。我在列X中有數據用於在列Z中創建數據。我希望Z全部爲1,直到X中有一行中有兩個0,然後是全零。另外,在W列中,我希望從底部向上看Y時最終的元素爲1,Y包含連續的兩個0。希望這是有道理的。我已經把Z欄和W欄放在了他們最終應該看的地方。我正在嘗試使用索引,但我很難弄清楚如何引用來自列X後面的行的Z行所在的行(因爲Z行1中的值基於值X中第2行和第3行)。這些應該是兩個獨立的功能,一個是看開始,一個是看結尾。它們都將分別應用到每一行,因此第X列將生成兩列,如下所示,以及另一列,在這種情況下將全爲0。謝謝你的幫助!如何根據行上/下的行中的值創建列R

** * ** *我改變的列名從A B C d到X YŽW至避免混淆。對不起,當我輸入它時沒有想到!

** * ** * ** * *我真的希望能夠做到這一點沒有功能或循環,只使用索引。我想我可以使用一個函數來解決它,但由於它是一個大型數據集,我希望它儘可能快。

code X Y Z W 
A 1 0 1 0 
A 1 0 1 0 
A 0 0 1 0 
A 1 0 1 0 
A 1 0 1 0 
A 1 0 1 0 
A 1 0 1 0 
A 0 0 1 0 
A 1 0 1 0 
A 0 0 0 0 
A 0 0 0 0 
A 1 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 1 1 0 0 
B 0 0 0 0 
B 1 0 0 0 
B 0 0 0 0 
B 1 0 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 1 0 0 0 
B 0 1 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 0 1 0 1 
B 0 1 0 1 
B 0 1 0 1 
B 0 0 0 1 
B 0 1 0 1 
B 0 1 0 1 

以下用於聚合的函數應該給出我正在尋找的結果。感謝泰勒開始這個功能。我仍然覺得應該有一個更簡單的方法來做到這一點,但現在應該這樣做。感謝大家的投入!

我想我明白了,基於泰勒的代碼,只是做了一些改變。我將只使用聚合應用這個函數,它應該全部解決。感謝所有的投入!

pat.finder <- function(var, value=0, fill1=1, fill2=0, rev=FALSE, seq=2){ 

if(var[1]==0 & rev==FALSE){ 

j<- rep(0,length(var))} else if(var[length(var)]==0 & rev == TRUE){ 

j<- rep(0,length(var))} else{ 

x <- if(rev) rle(rev(var)) else rle(var) 
n <- which(x[[1]]>(seq-1) & x[[2]]==value)[1]-1 
i <- sum(x[[1]][1:n]) 
j <- if(rev){ 
      rev(c(rep(fill1, i), rep(fill2, length(var)-i))) 
     } else { 
      c(rep(fill1, i), rep(fill2, length(var)-i)) 
     } 
} 

return(j) 
} 
+0

我看看'zoo'包中的'rollapply()'。像'which(rollapply(zoo(DF $ A,width = 2,function(X)all(X == 0)))[1]'''''''''''''''''''''''''''''''''''''''' '這是0,然後是0. – 2012-02-23 20:05:05

回答

1

有可能是一個更快的方法,但是這是我想出了:

dat <- read.table(text="code A B C D #read in your data 
A 1 0 1 0 
A 1 0 1 0 
A 0 0 1 0 
A 1 0 1 0 
A 1 0 1 0 
A 1 0 1 0 
A 1 0 1 0 
A 0 0 1 0 
A 1 0 1 0 
A 0 0 0 0 
A 0 0 0 0 
A 1 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
A 0 0 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 1 1 0 0 
B 0 0 0 0 
B 1 0 0 0 
B 0 0 0 0 
B 1 0 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 1 0 0 0 
B 0 1 0 0 
B 0 0 0 0 
B 0 0 0 0 
B 0 1 0 1 
B 0 1 0 1 
B 0 1 0 1 
B 0 0 0 1 
B 0 1 0 1 
B 0 1 0 1", header=T) 

現在代碼:

A.rle <- rle(dat$A) 
n <- which(A.rle[[1]]>1 & A.rle[[2]]==0)[1]-1 
i <- sum(A.rle[[1]][1:n]) 
dat$C <- c(rep(1, i), rep(0, nrow(dat)-i)) 

B.rle <- rle(rev(dat$B)) 
n2 <- which(B.rle[[1]]>1 & B.rle[[2]]==0)[1]-1 
i2 <- sum(B.rle[[1]][1:n2]) 
dat$D <- rev(c(rep(1, i2), rep(0, nrow(dat)-i2))) 

編輯:我不完全理解你想要什麼我認爲,所以我試圖創建一個功能,以滿足您的需求。使用rev=TRUE看看到底:

pat.finder <- function(var, value=0, fill1=1, fill2=0, rev=FALSE, seq=2){ 
    x <- if(rev) rle(rev(var)) else rle(var) 
    n <- which(x[[1]]>(seq-1) & x[[2]]==value)[1]-1 
    i <- sum(x[[1]][1:n]) 
    j <- if(rev){ 
       rev(c(rep(fill1, i), rep(fill2, length(var)-i))) 
      } else { 
       c(rep(fill1, i), rep(fill2, length(var)-i)) 
      } 
    return(j) 
} 

#TRY IT OUT 
pat.finder(dat$B, rev=TRUE) 

transform(dat, C=pat.finder(A), D = pat.finder(B, rev=TRUE)) #what I think you want 

transform(dat, C=pat.finder(A, fill1='foo', fill2='bar'), 
    D = pat.finder(A, rev=TRUE)) 

transform(dat, C=pat.finder(A, value=1), D = pat.finder(B, rev=TRUE)) 
+0

好吧,對不起,我正在編輯,然後達到了時間限制:感謝您的開始,唯一的問題是「代碼」列中有近500種不同的可能性,所以我需要一個單獨引用這部分數據的方式,而不是爲每個數據創建單獨的變量(並且我想避免執行循環)。這是我目前所擁有的,其中C最初只是一列0。但是,顯然這是行不通的。 C [A [as.numeric(rownames(A))+ 1]!= 1&A [as.numeric(rownames(A))+ 2]!= 1] < - 1我需要rownames()只是不知道是什麼。 – user1228982 2012-02-23 19:50:13

+0

@ user1228982 - 如果你願意,你可以隨時刪除你以前的評論之一(因爲一旦你得到它,我會做這件事)。歡呼,歡迎來到SO! – 2012-02-23 19:59:55

+0

我認爲在將這個功能放入功能後,它應該能夠滿足您的需求。我在轉換中使用它,因爲這更容易,代碼更少,但是可以使用隔離每列的函數:'pat.finder(var,value = 0,fill1 = 1,fill2 = 0,rev = FALSE,seq = 2)' 。 var是你的列,value是你要查找的模式,fill1是你想要填充字符串的第一部分的內容,fill2與下半部分是相同的,rev給你看後面的能力列的結尾,seq會告訴您要查找的模式有多少次重複。 – 2012-02-23 20:11:24

1

考慮sum(dat$A[i:(i+1)])。如果你連續有兩個零,那就是零。使用循環(或lapply)或其中一個運行函數來查找返回零的最小「i」,並且您已找到將C列從1切換到0的位置。我真的不得不問:「你想解決什麼問題?」我幾乎可以保證,如果您告訴我們A列和B列的數據來自哪裏,我們可以向您展示更直接的方法來確定您在C列和D列設置的斷點。

PS:一旦一個解決方案是設立dat$C,只是做相同,但由「IMAX」 1向下循環,從而獲得dat$D

+0

基本上,列X和Y中的數據表示與A關聯的值是否小於與A關聯的數據的第一個四分位數。此外,如果該特定行的日期更長,則X僅給出值1比某個日期。 X欄基本上在尋找「新」項目。如果該特定行的日期少於特定日期,則Y列僅給出1。 Y欄基本上在尋找已經停產的物品。列Z和W在那裏通過創建一個具有更好定義模式的向量來進一步優化這個過程。非常清楚,對吧? – user1228982 2012-02-23 21:16:47

1

這可能適用於您的需求(只做A列)。如果您可以更具體地瞭解您正在尋找什麼,董事會可以進一步提供幫助。

## read in your data 
df1 = read.table(text="code A B C D 
A 1 0 1 0 
A 1 0 1 0 
... 
") 

## create forward-lagged A column 
require(taRifx) 
df1$lagA = shift(df1$A,wrap=F,pad=T) 

myfun1 = function(x,y) { 
    BB = x + y 
    BB = ifelse(BB > 0, 1, 0) 
    BB 
} 

df1$A2 = apply(df1[,c(2,6)], 1, function(x,y) myfun1(x[1],x[2])) 
tvec = rep(1,which(df1$A2 == 0)[1] -1) 
bvec = vector(length = nrow(df1) - which(df1$A2 == 0)[1] + 1, mode="numeric") 

## the column you are looking for: 
df1$nA = c(tvec,bvec) 
+0

您可能會在'taRifx'包中找到'shift'函數對此有所幫助。如果你的'flagum'函數做到了我認爲的那樣,'shift'可以做同樣的事情和更多。 – 2012-02-23 20:42:40

+0

酷;謝謝。然後,我可以替換上面的代碼來讀取df1 $ lagA = shift(df1 $ A,wrap = F,pad = T)。 – 2012-02-23 22:24:39

+0

是的。這是主意。 – 2012-02-23 23:21:59

1

假設問題中顯示的數據幀是DF。那麼如果x的第i個元素和下一個元素是0並且結果的第i個元素否則爲1,那麼pmax的結果的第i個元素爲0。由於'x'的最後一個元素沒有下一個元素,我們在末尾附加1。然後,我們將其與0進行比較,然後將cummin移到此過程中發現的前0個位置。

two0 <- function(x) cummin(c(pmax(x[-1], x[-length(x)]), 1) != 0) 
DF.out <- transform(DF, Z = two0(X), W = rev(two0(rev(Y)))) 

!=0使得two0integer結果。如果我們希望我們可以放棄它,結果將是numeric

編輯:澄清的整數/數字方面。

+0

比我的解決方案更流暢。 – 2012-02-23 22:45:23