将列(长)的级别重新整理为新列(宽)

时间:2016-08-08 01:11:34

标签: r dataframe apply

我想在一个DF中获取列的级别,并将每个级别添加为新DF中的新列。这是一个玩具数据集,显示源和理想目标DF。

来源DF

person  hour  ride 
Bill     1      A
Sue      2      B
Bob      1      C
Jill     3      B
Dan      3      A
Tina     3      A

映射DF

hour   A   B   C   Saturation 
1      1   0   1     .66
2      0   1   0     .33
3      1   1   0     .66

这是一个测试数据集:

test_data <- cbind.data.frame(person = c('Bill', 'Sue', 'Bob', 'Jill', 'Dan', 'Tina'),
                              hour = factor(c(1, 2, 1, 3, 3, 3)),
                              ride = c('A', 'B', 'C', 'B', 'A', 'A'))

test_data$person <- as.character(test_data$person)

了解Source中的每次乘坐如何变成Mapped中的新列。我可以通过

获得关卡并使用它们来创建映射的DF
new_data <- cbind.data.frame(hour = levels(test_data$hour))

但是当我尝试迭代级别来添加新列时,它都失败了。我看到了水平。

unlist(lapply(levels(test_data$ride), function(x) paste(x)))

产量

[1] "A" "B" "C"

那么如何浏览$ride中的级别并在映射的DF中添加一列?

额外奖励:我将在test_dataifelse()中的每一行和1中的每一行中显示与该骑行相对应的行,以显示它有骑手,以及0否则,但有人必须看到如何更优雅地做到这一点?就目前情况而言,我需要ifelse$ride中的级别中提取的每个列,我知道这些级别必须比要求的更详细。

2 个答案:

答案 0 :(得分:1)

require(reshape2)

mydat <- recast(test_data,hour~ride)
mydat
  hour A B C
1    1 1 0 1
2    2 0 1 0
3    3 2 1 0
# 2nd part
for(i in 2:ncol(mydat)){
  for(ii in 1:nrow(mydat)){
    if(mydat[ii,i] > 0) {mydat[ii,i] <- 1}
  }
}
  hour A B C
1    1 1 0 1
2    2 0 1 0
3    3 1 1 0

答案 1 :(得分:0)

我们可以使用dcast

中的data.table
library(data.table)
dcast(setDT(test_data), hour~ride, value.var="person", 
               function(x) as.integer(length(x) > 0))[, 
        Saturation := round(rowSums(.SD)/3,2), .SDcols = A:C][]
#    hour A B C Saturation
#1:    1 1 0 1       0.67
#2:    2 0 1 0       0.33
#3:    3 2 1 0       1.00