2015-05-10 41 views
1

我有一組10年的R貢獻數據。美元價值根據ID#(給予禮物的人)和給出的年份進行分組。每年都沒有每個人的禮物。對於每一行,我想表明行(禮物)是否是第一筆捐獻(從未給出過),如果與上一年相同,大於上一年,小於上一年,如果沒有在前一年的禮物(但前一年有禮物)。另外,我想說明送禮的人是否在下一年沒有送禮。根據年度價值變化創建R中的新列

因此,如果數據是這樣的:

ID#   YEAR   GIFT 
1    2005   $10 
1    2006   $5 
1    2008   $15 
1    2009   $20 
1    2010   $20 


the result should be: 

ID#   YEAR   GIFT   STATUS 
1    2005   $10   FIRST 
1    2006   $5   LOWER   also NO NEXT YEAR 
1    2008   $15   PREVIOUS GIVER 
1    2009   $20   HIGHER 
1    2010   $20   SAME 

謝謝!

+0

這將是很好,如果你的例子是可重複的,在這裏描述的意義上:http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example因爲它是,目前還不清楚你的專欄是否是因素或字符/字符串。 – Frank

+1

對不起,我是新來的(第一個問題)。我願意將這些年份的性格,數字或因素作爲最佳工作方式。禮物是數字,ID#是優選的因素/字符,但如果需要可以是數字。 – Dave1956

+0

看看'data.table'開發版本中的'shift'函數(關於SO的一些最近的問題應該給你舉例)。這將回答你的大部分問題。 'dt [,first:=。I == 1,by = id]'會給你第一個禮物的指示器(確保它是按年排序的) – MichaelChirico

回答

1

使用dplyr和函數來確定結果並使代碼更清潔的解決方案。數據:

data <- read.table(text="ID   YEAR   GIFT 
1    2005   $10 
1    2006   $5 
1    2008   $15 
1    2009   $20 
1    2010   $20", header=TRUE) 

爲了得到你想要的,我們必須比較每個值(this),以它的前面(prev)輸出,下一個(follow),並檢查它的first或組last

getStatus <- function(first, prev, this, follow, last) { 
    if (first) { 
    status <- "FIRST" #Easy one 
    } else if (length(prev) < 1 || is.na(prev)) { #Not the first, but prev missing 
    status <- "PREVIOUS GIVER" 
    } else if (this < prev) { #The next 3 are obvious 
    status <- "LOWER" 
    } else if (this == prev) { 
    status <- "SAME" 
    } else if(this > prev) { 
    status <- "HIGHER" 
    } 
    if ((length(follow) < 1 || is.na(follow)) & !last) { #No next but isn't last 
    status <- paste(status, "also NO NEXT YEAR") 
    } 
    return(status) 
} 

現在我們有了我們的功能,我們必須處理數據。我們將使用dplyr使事情更具可讀性。

library(dplyr) 

result <- data %>% group_by(ID) %>% 
    arrange(YEAR) %>% #We make sure YEAR is sorted ascending 
    mutate(gift.num = GIFT %>% gsub("\\$", "", .) %>% as.numeric) %>% #Create a column with the gifts as numbers 
    mutate(RESULT = sapply(YEAR, function(y) { 
    #Apply getStatus passing the corresponding arguments to create RESULT 
    getStatus(.$YEAR %>% first == y, .$gift.num[which(.$YEAR==y-1)], 
       .$gift.num[which(.$YEAR==y)], .$gift.num[which(.$YEAR==y+1)], 
       .$YEAR %>% last == y) 
    })) %>% 
    select(-gift.num) #Removing the dummy column 

這給我們:

ID YEAR GIFT     RESULT 
1 1 2005 $10     FIRST 
2 1 2006 $5 LOWER also NO NEXT YEAR 
3 1 2008 $15   PREVIOUS GIVER 
4 1 2009 $20     HIGHER 
5 1 2010 $20     SAME 

更多的數據會更好,以確保所有情況下都包括在內,但即使沒有,與你應該能夠修復任何錯誤。

+0

謝謝!這絕對讓我朝着正確的方向前進。正如你所說的,它需要用更多的數據進行一些調試,但是我真的很感謝幫助! – Dave1956