R-从字符列中的值创建动态指标列

时间:2018-07-29 02:24:14

标签: r

我有如下数据:

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...

谢谢!

2 个答案:

答案 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 Rtable中执行此操作,方法是将“ 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