dplyr加入并保持变量obs而不用NA

时间:2015-04-10 02:38:33

标签: r dplyr

我有一个for循环,根据tdata$me和10%分位数分配投资组合。我遇到的问题是当我运行for循环时,我最终只有分配的投资组合的最后一个观察年。在我循环这些年的过程中,我们的想法是放置组合分配portf,然后将其与更大的数据集连接起来。

我的问题是如何在不将NA放入所有其他未知障碍物的情况下加入两个数据集,而是保持障碍物原样?

此外,还有更好的方法可以使用for运行此dplyr循环吗?这似乎是一种分配投资组合的低效方式,但我想不出另一种方式。

可重复的例子:

tdata <- structure(list(cusip = c(47L, 47L, 47L, 47L, 47L, 47L, 47L, 47L, 
    47L, 47L, 47L, 47L, 47L, 47L, 47L, 47L, 47L, 47L, 47L, 47L), 
    fyear = c(1970L, 1970L, 1970L, 1970L, 1970L, 1970L, 1970L, 
    1970L, 1970L, 1970L, 1970L, 1970L, 1971L, 1971L, 1971L, 1971L, 
    1971L, 1971L, 1971L, 1971L), me = c(157,115,  45,  19, 132,  21, 147,
    191,  80, 165,  32, 100,  44, 134, 104,9, 183, 163, 109,  88), month = c(6L, 6L, 6L, 6L, 6L, 
    6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 
    8L)), .Names = c("cusip", "fyear", "me", "month"), row.names = c(NA, 
    20L), class = "data.frame")

for(i in unique(tdata$fyear)){
  check <- filter(tdata, month == 06 & fyear == i)                         ###
  per <- quantile(check$me, c(.10, .20, .30, .40, .50, .60, .70, .80, .90))
  check$portf[check$me < per[[1]]] <- "A"
  check$portf[check$me >= per[[1]] & check$me < per[[2]]] <- "B"
  check$portf[check$me >= per[[2]] & check$me < per[[3]]] <- "C"
  check$portf[check$me >= per[[3]] & check$me < per[[4]]] <- "D"
  check$portf[check$me >= per[[4]] & check$me < per[[5]]] <- "E"
  check$portf[check$me >= per[[5]] & check$me < per[[6]]] <- "F"
  check$portf[check$me >= per[[6]] & check$me < per[[7]]] <- "G"
  check$portf[check$me >= per[[7]] & check$me < per[[8]]] <- "H"
  check$portf[check$me >= per[[8]] & check$me < per[[9]]] <- "I"
  check$portf[check$me >= per[[9]]]  <- "J"
  check <- select(check, cusip, fyear, portf)
  testcrsp <- left_join(tdata, check, by = c("cusip", "fyear"))  ######
}

1 个答案:

答案 0 :(得分:1)

<强>更新

dplyr解决方案,用于删除for循环。注意我删除了length()部分,因为我不确定如何在dplyr上执行此操作而不重复breaks代码。结果略有不同,因为它仅返回带months==6的数据框,而不是NA所有未选择月份的数据。

tdata3 <- tdata %>% group_by(fyear) %>%
  filter(month==6) %>% 
  mutate(portf = cut(me, labels=LETTERS[1:10], include.lowest=TRUE, breaks=(me %>% quantile(seq(0, 1, by=0.1)) %>% unique)) %>%      
  as.character) %>% ungroup

<强>原始

这就是我想你想要的。它不使用dplyr,因为您不需要它来简单地子集和循环这些年。它确实使用cutme列分位数分割为字母因子。

tdata2 <- tdata
for (i in unique(tdata$fyear)) {
  thisyear <- tdata[tdata$fyear==i & tdata$month==6,]
  per <- unique(quantile(thisyear$me, seq(0, 1, by=0.1))) 
  factors <- cut(thisyear$me, breaks=per, labels=LETTERS[1:(length(per)-1)], include.lowest=TRUE)  
  tdata2$portf[tdata$fyear==i & tdata$month==6] <- as.character(factors)
}

tdata2
#    cusip fyear  me month portf
# 1     47  1970 157     6     I
# 2     47  1970 115     6     F
# 3     47  1970  45     6     C
# 4     47  1970  19     6     A
# 5     47  1970 132     6     G
# 6     47  1970  21     6     A
# 7     47  1970 147     6     H
# 8     47  1970 191     6     J
# 9     47  1970  80     6     D
# 10    47  1970 165     6     J
# 11    47  1970  32     6     B
# 12    47  1970 100     6     E
# 13    47  1971  44     6     B
# 14    47  1971 134     6     G
# 15    47  1971 104     6     D
# 16    47  1971   9     6     A
# 17    47  1971 183     6     J
# 18    47  1971 163     6     I
# 19    47  1971 109     6     E
# 20    47  1971  88     8  <NA>

# 0%   10%   20%   30%   40%   50%   60%   70%   80%   90%  100% 
#    A     B     C     D     E     F     G     H     I     J    

请注意,必须在分位数中使用唯一,因为您可以(在编辑数据之前发生)具有相等的分位数,这些因子不会被breaks接受。另外,如果直接键入length(per),则应使用1:10