我有如下数据:
library(dplyr)
d<-data.frame(ID=c(1,1,2,3,3,4), Quality=c("Good", "Bad", "Ugly", "Good", "Good", "Ugly"), Area=c("East", "North", "North", "South", "East", "North"))
我想做的是为Quality中的每个唯一值创建一个新列,并用ID是否与该值匹配来填充它,然后汇总ID。我想对Area做同样的事情。
当质量==好时,这就是我的目的:
d$Quality.Good <- 0
d$Quality.Good[d$Quality=="Good"] <- 1
e <- d %>%
group_by(ID) %>%
summarise(n=n(), MAX.Quality.Good = max(Quality.Good))
e
输出
A tibble: 4 x 3
ID MAX.Quality.Good
<dbl> <dbl>
1 1 1
2 2 0
3 3 1
4 4 0
是否可以构建一个遍历每个字符列并为“好”,“坏”,“丑陋”,“北”,“东”,“南”建立指示符的函数,而不是多次复制以上内容?
在这里我被困住了:
library(stringr)
#vector of each Quality
e <-d %>%
group_by(Quality) %>%
summarise(n=n()) %>%
select(Quality)
e<-as.data.frame(e)
#create new column names
f <- str_c(names(e),".",e[,1])
#initialize list of new columns
d[f] <- 0
#I'm stuck after this...
谢谢!
答案 0 :(得分:1)
1)基本R 为每列创建模型矩阵(使用函数make_mm
)并将其绑定为数据框m
。最后在ID
上汇总。不使用任何软件包。
make_mm <- function(nm, data) model.matrix(~ . - 1, data[nm])
m <- do.call("data.frame", lapply(names(d)[-1], make_mm, d))
with(d, aggregate(. ~ ID, m, max))
给予:
ID QualityBad QualityGood QualityUgly AreaEast AreaNorth AreaSouth
1 1 1 1 0 1 1 0
2 2 0 0 1 0 1 0
3 3 0 1 0 1 0 1
4 4 0 0 1 0 1 0
2)dplyr / purrr 可以将其替换为以下代码,该代码与问题代码相似,但可以归纳为所有必填列。请注意,这里我们使用make_md
制作模型数据帧,而不是使用make_mm
制作模型矩阵。另外请注意,group_by(m, ID = .$ID)
中的点是指d
而不是m
。
library(dplyr)
library(purrr)
make_md <- function(nm, data) {
data %>%
select(nm) %>%
model.matrix(~ . - 1, .) %>%
as.data.frame
}
d %>% {
m <- map_dfc(names(.)[-1], make_md, .)
group_by(m, ID = .$ID) %>%
summarize_all(max) %>%
ungroup
}
答案 1 :(得分:1)
我们可以使用base R
在table
中执行此操作,方法是将“ ID”列复制为数据集的列数减去1,然后paste
用{{ 1}}个值(“ ID”列除外)
unlist
或将table(rep(d$ID, 2), paste0(names(d)[-1][col(d[-1])], unlist(d[-1])))
# AreaEast AreaNorth AreaSouth QualityBad QualityGood QualityUgly
# 1 1 1 0 1 1 0
# 2 0 1 0 0 0 1
# 3 1 0 1 0 2 0
# 4 0 1 0 0 0 1
,tidyverse
转换为'long'格式,将{key1,'val'列gather
更改为单列,获得unite
行,并且在创建1秒的列后将distinct
设置为“宽”格式。
spread