2017-08-13 71 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