我有一个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")) ######
}
答案 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
,因为您不需要它来简单地子集和循环这些年。它确实使用cut
将me
列分位数分割为字母因子。
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
。