2016-05-17 41 views
10

开始数据帧应用匹配,更换了一系列的数据帧行的功能,以

data_start <- data.frame(marker = c("yes","yes","no","yes","no"), 
         id_out = c(5,3,1,1,7), 
         id_new = c(6,8,9,4,2)) 

> data_start 
    marker id_out id_new 
1 yes  5  6 
2 yes  3  8 
3  no  1  9 
4 yes  1  4 
5  no  7  2 

下方空列添加三个列标题。附加开始var1:var3值。

data_start[,c("var1", "var2", "var3")] <- NA 
vars <- c(5,3,1) 
data_start[1, 4:6] <- vars 

> data_start 
    marker id_out id_new var1 var2 var3 
1 yes  5  6 5 3 1 
2 yes  3  8 NA NA NA 
3  no  1  9 NA NA NA 
4 yes  1  4 NA NA NA 
5  no  7  2 NA NA NA 

我想通过应用功能,每行,其中IF = yesid_out匹配任何var1:var3的更新我var1:var3列,id_new更换任何的var1:var3。我找到了这个解决方案,但是适用于一行代码,并且仍然需要更新该行的每个新的var1:var3部分。

data_start[1, 4:6][data_start[1, 4:6] == data_start[1,"id_out"]] <- data_start[1,"id_new"] 

每行还取决于在再次应用函数之前使用上述行中的值。

当标记= no并且随后更新每行时,最终输出将如下所示,其中行保持不变。

> data_final 
    marker id_out id_new var1 var2 var3 
1 yes  5  6 6 3 1 
2 yes  3  8 6 8 1 
3  no  1  9 6 8 1 
4 yes  1  4 6 8 4 
5  no  7  2 6 8 4 

回答

1

这是可能的任何数量的列使用,并与基础R的工作原理:

cols <- c("var1", "var2", "var3") 

for(j in 1:length(cols)) { 
    var <- cols[j] 
    for(i in 1:nrow(data_start)){ 
    if(i > 1) { 
     data_start[i, var] <- data_start[i-1, var] 
    } 
    if(data_start[i, "marker"] == "yes" & data_start[i, var] == data_start[i,"id_out"]) { 
     data_start[i,var] <- data_start[i, "id_new"] 
    } 
    } 
} 
+0

谢谢,终于回来了,它的工作原理如预期。 – panstotts

0

这是非常粗糙的因为我必须运行,但这应该工作。

data_start <- data.frame(marker = c("yes","yes","no","yes","no"), 
         id_out = c(5,3,1,1,7), 
         id_new = c(6,8,9,4,2)) 

data_start[,c("var1", "var2", "var3")] <- NA 
vars <- c(5,3,1) 
data_start[1, 4:6] <- vars 

onVars <- c("var1", "var2", "var3") 

for (i in 2:nrow(data_start)) { 

    print(i) 

    for (var in onVars) { 

    if (data_start$marker[i] == "yes" & data_start$id_out[i] == data_start[i - 1, var]) { 

     data_start[i, var] <- data_start$id_new[i] 

    } else { 

     data_start[i, var] <- data_start[i - 1, var] 

    } 

    } 

} 

data_start是您的输出。

糟糕,看起来像我可能已经没有评估第一行,但希望你现在可以自己处理。

0

这里是一个片段,让你做这个计算,即使你有超过三列:

library(data.table) 
dt <- data.table(marker = c("yes","yes","no","yes","no"), 
         id_out = c(5,3,1,1,7), 
         id_new = c(6,8,9,4,2)) 

dt[, change := cumsum(marker == "yes")] 

ref.new <- dt[marker == "yes", id_new] # Reference to values where marker is "yes" 
ref.out <- dt[marker == "yes", id_out] 
for (x in 1:length(ref.new)) { 
    dt[, paste("var", x, sep="") := ifelse(change >= x, ref.new[x] , ref.out[x])] 
} 
head(dt) 
#  marker id_out id_new change var1 var2 var3 
#1: yes  5  6  1 6 3 1 
#2: yes  3  8  2 6 8 1 
#3:  no  1  9  2 6 8 1 
#4: yes  1  4  3 6 8 4 
#5:  no  7  2  3 6 8 4 
+0

这是一个有趣的方法,但它似乎像我们假定你是这里的一些模式在未被提及OP,所以我不知道这是偶然的工作还是这真的应该是什么 –

+0

我想我知道你的意思..以及很容易改变任何一种方式,我只是使用最直接的选项。 – Bulat

0

这似乎很难找到一个解决方案,而for循环,如果,所以在这儿呢。我试图用其他设置如c(1,3,1)更改原始值,并且代码正常工作。如果需要,我们也可以添加更多的变量列。

# Re-create the data 
dt <- data.table(marker = c("yes","yes","no","yes","no"), 
       id_out = c(5,3,1,1,7), 
       id_new = c(6,8,9,4,2)) 
var.col <- paste0("var", 1:3) 
dt[1, (var.col) := .(5,3,1)] 

# Processing 
for(i in 1:nrow(dt)) { 
    if(i > 1) dt[i, (var.col) := as.list(dt[i-1, var.col, with = F])] 
    var.i <- dt[i, var.col, with = F] %in% dt[i, id_out] 
    if(dt[i]$marker == 'yes' & sum(var.i) != 0) { 
    dt[i, (var.col[var.i]) := dt[i, id_new]] 
    } 
} 
相关问题