2017-08-13 70 views
2

我是R新手,現在我知道dplyr。我需要在我的數據框中的每個Id中關聯不同的月份(列YM)。我很困擾它,因爲我甚至不知道把它們正確地與id相關聯的時候把它放在哪裏,可能是我可以通過我的id訪問的列表? 對於協會id月,我想到了spread函數tidyr,但我無法做到這一點。這裏的數據集的示例:創建與我的ID相關的不同月份的矢量

Id  YM 
103285 201401 
103285 201402 
103285 201410 
103285 201411 
103285 201412 
103285 201501 
103285 201502 
103346 201408 
103346 201409 
103346 201410 
103346 201411 
103346 201412 
103346 201501 
103346 201502 

預期結果:

103285 c(01, 02, 10, 11, 12) 
103346 c(08, 09, 10, 11, 12, 01, 02) 

回答

0

一種替代方法是使用通過split ID,打破了YM變量,然後通過結果列表與lapply運行。 substring將ym中最後兩個字符的子字符串和unique刪除重複值。這將返回一個命名列表,其中每個列表項的名稱都是該ID。

lapply(split(dat$YM, dat$Id), function(x) unique(substring(x, nchar(x)-1L))) 
$`103285` 
[1] "01" "02" "10" "11" "12" 

$`103346` 
[1] "08" "09" "10" "11" "12" "01" "02" 

如果我們知道,在YM的值將永遠是6個字符,我們可以用substring(x, 5)substring(x, 5, 6)更換substring(x, nchar(x)-1L)。返回的值是字符,保留前導0.

如果您不介意丟失前導0,則可以使用模數運算符。

lapply(split(dat$YM, dat$Id), function(x) unique(x %% 100)) 
$`103285` 
[1] 1 2 10 11 12 

$`103346` 
[1] 8 9 10 11 12 1 2 

如果保持領先的0是非常重要的,你可以將它們添加回來sprintf

lapply(split(dat$YM, dat$Id), function(x) sprintf("%02.0f", unique(x %% 100))) 
$`103285` 
[1] "01" "02" "10" "11" "12" 

$`103346` 
[1] "08" "09" "10" "11" "12" "01" "02" 
+0

感謝LMO,學習這可能是另一種選擇的緣故? – fedezi

+0

@fedezi我已經添加了第三個選項,如果在使用模數運算符後需要前導0。 – lmo

0

我認爲基礎R是更好地在這裏適用,但dplyr一個可能的解決方案:

library(dplyr) 
df %>% group_by(Id) %>% 
summarize(months = list(unique(substr(YM,5,6)))) %>% 
as.data.frame 

輸出:

 Id      months 
1 103285   01, 02, 10, 11, 12 
2 103346 08, 09, 10, 11, 12, 01, 02 

注意的是,幾個月來都在列表中,因此要獲得對應於103285月的載體,你要做的:

x$months[x$Id==103285][[1]] 

而用改性活生物體的解決方案,你可以簡單地做

x['103285'] 

找到相同的矢量。

0

tidyRnest功能,你可以這樣做:

library(dplyr) 
library(tidyR) 
df1 %>% mutate(YM =substr(YM,5,6)) %>% unique %>% nest(YM,.key=YM) %>% as.data.frame 
     Id       YM 
1 103285   01, 02, 10, 11, 12 
2 103346 08, 09, 10, 11, 12, 01, 02 
0
aggregate(YM~Id, df, function(x) 
    unique(substr(x, nchar(x)-1, nchar(x))), simplify = FALSE) 
#  Id       YM 
#1 103285   01, 02, 10, 11, 12 
#2 103346 08, 09, 10, 11, 12, 01, 02 

OR

aggregate(YM~Id, df, function(x){ 
    unique(format(as.Date(paste0(x, 01), format = "%Y%m%d"), "%m")) 
}, simplify = FALSE) 
#  Id       YM 
#1 103285   01, 02, 10, 11, 12 
#2 103346 08, 09, 10, 11, 12, 01, 02