R:使用另一列的值将多个列折叠为一列

时间:2016-07-21 04:54:18

标签: r

我的数据如下:

# Create fake data frame
score <- rep(seq(1:3), 2)
id <- rep(c(2014, 2015), each = 3)
var_if_1 <- rep(c(0.1, 0.8), each = 3)
var_if_2 <- rep(c(0.9, 0.7), each = 3)
var_if_3 <- rep(c(0.6, 0.2), each = 3)
data.frame(score, id, var_if_1, var_if_2, var_if_3)

更具体地说,每一行由数据框中的两个向量唯一定义(例如得分和id),并且有许多以字符串开头的附加列(例如&#34; var_if _&#34;)和结束用不同的数字(例如1,2,3)。此外,对于给定的分数值(即对于具有给定分数的任何行),附加变量的值不会变化。

我正在尝试将这些数据转换为如下所示的数据框:

# Desired output data frame
score <- rep(seq(1:3), 2)
id <- rep(c(2014, 2015), each = 3)
var <- c(0.1, 0.9, 0.6, 0.8, 0.7, 0.2)
data.frame(score, id, var)

更具体地,附加变量(var_if_#)被移除并聚合成单个新变量(例如var),该变量基于得分值取得一个附加变量列的值。例如,如果得分== 2,则var == var_if_2。

解决方案的约束

  • 希望使用base R或dplyr()。
  • 寻找能够推广大量“得分”值的解决方案。以及&#39; var_if _#&#39;的相应列和任意排序的行。

下面举例说明了任意行排序。

score <- rep(seq(1:3), 2)
id <- rep(c(2014, 2015), each = 3)
var_if_1 <- rep(c(0.1, 0.8), each = 3)
var_if_2 <- rep(c(0.9, 0.7), each = 3)
var_if_3 <- rep(c(0.6, 0.2), each = 3)
foo <- data.frame(score, id, var_if_1, var_if_2, var_if_3)
foo[sample(1:nrow(foo)), ]  # arbitrary row order

我也知道我可以使用ifelse()但这会变成    很多可能的分数值很繁琐(除非有循环    可以减少乏味的方法。

2 个答案:

答案 0 :(得分:4)

使用矩阵索引,避免慢速循环或apply逻辑:

cbind(dat[1:2], var=dat[3:5][cbind(seq_len(nrow(dat)), dat$score)])
#  score   id var
#1     1 2014 0.1
#2     2 2014 0.9
#3     3 2014 0.6
#4     1 2015 0.8
#5     2 2015 0.7
#6     3 2015 0.2

如果您专门匹配var_if_1等名称模式,请使用match获取要提取的列:

dat[cbind( seq_len(nrow(dat)), match(paste0("var_if_", dat$score), names(dat)))]

答案 1 :(得分:2)

您可以使用函数apply,它将迭代数据框的每一行。如果列的特定顺序如下所示:

var <- apply(my_data_frame, 1, function(x) { x[x["score"] + 2] })

如果您想使用列的名称而不是其位置,可以将x["score"] + 2]替换为x[paste0("var_if_",x["score"])]