df <- as.data.frame(cbind(c(1:10), c(15, 70, 29, 64, 57, 29, 10, 80,81, 71)))
V1 V2
1 1 15
2 2 70
3 3 29
4 4 64
5 5 57
6 6 29
7 7 10
8 8 80
9 9 81
10 10 71
cuts <- c(5, 10, 90, 95)
我想为所有(在本例中为四个)切割值x
(例如P5
,P10
,P90
和{{1}创建逻辑变量})表示是否P95
。 “手动”添加变量的简单方法不会扩展到少数几个:
v2 <= x
显然,为了使数据保持“整洁”格式,应该应用最终df %<>%
mutate( P5 = V2 <= 5) %>%
mutate(P10 = V2 <= 10) %>%
mutate(P90 = V2 <= 90) %>%
mutate(P95 = V2 <= 95)
V1 V2 P5 P10 P90 P95
1 1 15 FALSE FALSE TRUE TRUE
2 2 70 FALSE FALSE TRUE TRUE
3 3 29 FALSE FALSE TRUE TRUE
4 4 64 FALSE FALSE TRUE TRUE
5 5 57 FALSE FALSE TRUE TRUE
6 6 29 FALSE FALSE TRUE TRUE
7 7 10 FALSE TRUE TRUE TRUE
8 8 80 FALSE FALSE TRUE TRUE
9 9 81 FALSE FALSE TRUE TRUE
10 10 71 FALSE FALSE TRUE TRUE
。
我尝试的替代方法是
gather(year, islegal, c(3;6))
显然,我会删除最后的do.call(rbind, lapply(cuts, function(x) {
df %>% mutate(year = x, islegal = V2 <= x)
})) %>% spread(year, islegal)
V1 V2 5 10 90 95
1 1 15 FALSE FALSE TRUE TRUE
2 2 70 FALSE FALSE TRUE TRUE
3 3 29 FALSE FALSE TRUE TRUE
4 4 64 FALSE FALSE TRUE TRUE
5 5 57 FALSE FALSE TRUE TRUE
6 6 29 FALSE FALSE TRUE TRUE
7 7 10 FALSE TRUE TRUE TRUE
8 8 80 FALSE FALSE TRUE TRUE
9 9 81 FALSE FALSE TRUE TRUE
10 10 71 FALSE FALSE TRUE TRUE
以使数据保持“整洁”格式。
问题:是否有更好或更通用的方法使用spread()
而不是第二种方法来自动创建变量(类似分位数的截止值,如此类,或虚拟或类似),不需要像第一种方法那样明确地输入{dplyr}
的内容吗?
答案 0 :(得分:6)
当然,你不需要dplyr这么简单。
names(cuts) <- paste0("p", cuts)
data.frame(df, lapply(cuts, function(x) df$V2 <= x))
V1 V2 p5 p10 p90 p95
1 1 15 FALSE FALSE TRUE TRUE
2 2 70 FALSE FALSE TRUE TRUE
3 3 29 FALSE FALSE TRUE TRUE
4 4 64 FALSE FALSE TRUE TRUE
5 5 57 FALSE FALSE TRUE TRUE
6 6 29 FALSE FALSE TRUE TRUE
7 7 10 FALSE TRUE TRUE TRUE
8 8 80 FALSE FALSE TRUE TRUE
9 9 81 FALSE FALSE TRUE TRUE
10 10 71 FALSE FALSE TRUE TRUE
答案 1 :(得分:4)
如果你想以编程方式&#34;与dplyr
合作,你应该看看&#34;标准评估&#34;通常版本的功能的替代品。请参阅非标准评估小插图(vignette("nse", "dplyr")
)。
除了mutate
函数之外,还有一个mutate_
函数允许您指定转换列表。在您的情况下,您可以使用类似的内容构建列表
cuts <- c(5,10,90,95)
mymutate <- setNames(lapply(cuts , function(x)
lazyeval::interp(~V2<=x, x=x)), paste0("P", cuts ))
然后您可以使用
执行转换df %>% mutate_(.dots=mymutate )
# V1 V2 P5 P10 P90 P95
# 1 1 15 FALSE FALSE TRUE TRUE
# 2 2 70 FALSE FALSE TRUE TRUE
# 3 3 29 FALSE FALSE TRUE TRUE
# 4 4 64 FALSE FALSE TRUE TRUE
# 5 5 57 FALSE FALSE TRUE TRUE
# 6 6 29 FALSE FALSE TRUE TRUE
# 7 7 10 FALSE TRUE TRUE TRUE
# 8 8 80 FALSE FALSE TRUE TRUE
# 9 9 81 FALSE FALSE TRUE TRUE
# 10 10 71 FALSE FALSE TRUE TRUE
答案 2 :(得分:0)
如果您计划最终将数据转换为整洁的数据,则可以从一个开始:
library(dplyr)
df <- as.data.frame(cbind(c(1:10), c(15, 70, 29, 64, 57, 29, 10, 80,81, 71)))
cuts <- data_frame(P=c(5, 10, 90, 95))
p_df <- df %>% tidyr::crossing(cuts) %>%
mutate(flag=V2<=P)
p_df
# V1 V2 P flag
#1 1 15 5 FALSE
#2 1 15 10 FALSE
#3 1 15 90 TRUE
#4 1 15 95 TRUE
#5 2 70 5 FALSE
#...
如果原始格式确实是您想要的,tidyr::spread
结果
p_df %>%
tidyr::spread(P, flag, sep="")
# V1 V2 P5 P10 P90 P95
#1 1 15 FALSE FALSE TRUE TRUE
#2 2 70 FALSE FALSE TRUE TRUE
#3 3 29 FALSE FALSE TRUE TRUE
#4 4 64 FALSE FALSE TRUE TRUE
#5 5 57 FALSE FALSE TRUE TRUE
#6 6 29 FALSE FALSE TRUE TRUE
#7 7 10 FALSE TRUE TRUE TRUE
#8 8 80 FALSE FALSE TRUE TRUE
#9 9 81 FALSE FALSE TRUE TRUE
#10 10 71 FALSE FALSE TRUE TRUE