根据匹配仅更新数据框的某些值

Updating only certain values of data frame based on match

我正在尝试根据匹配更新 lapply 内更高范围内的变量 (popsnp)。不过,我不太明白更新值的语法,我目前用 NA:

覆盖任何以前存在的值
lapply(1:22, function(i){
  in.name<-paste("/data/mdp14aps/ld/chr", i, ".ld", sep="")
  out.name<-paste("/data/mdp14aps/R/ldatachr", i, ".rda", sep="")
  ldata<-read.csv(in.name, sep="", header=TRUE,
                  colClasses=c(NA,NA,NA,NA,NA,NA,"NULL"))
  freq<-count(ldata, c("SNP_A", "CHR_A", "BP_A"))

  #the part I'm not sure about
  popsnp$chrom<<-freq[match(popsnp$marker, freq$SNP_A),2]
  popsnp$position<<-freq[match(popsnp$marker, freq$SNP_A),3]
  popsnp$freq<<-freq[match(popsnp$marker, freq$SNP_A),4]

  save(ldata,file=out.name)
  rm(ldata, freq)
})

我想保留我在 lapply 迭代之间设置的值,所以我最终得到 popsnp 包含 all 个值 chrompositionfreq,而不仅仅是最后一次迭代。

我觉得这应该很简单,但我对 R 还是有些陌生。

玩具示例:

test<-data.frame(A = c("a", "b", "c", "d", "e"), B = c(rep(NA,5)))
test1<-data.frame(A = c("a", "b"), B = c(1, 2))
test2<-data.frame(A = c("c", "d", "e"), B = c(3, 4, 5))

test$B<-test1[match(test$A, test1$A), 2]
test$B<-test2[match(test$A, test2$A), 2]

我希望 test$B 包含 1-5 的值。

玩具示例更新

您需要对作业的两边进行子集化,并将您的条件转换为逻辑子集化向量。

logical1 <- !is.na(test1[match(test$A, test1$A),2]) # TRUE/FALSE
logical2 <- !is.na(test1[match(test$A, test2$A),2])

test[t1,] <- test1[t1,] # selects only TRUE rows
test[t2,] <- test2[t2,] 

我建议您单独查看每个元素,以便了解发生了什么。


之前...

我不太确定我理解你的例子想要完成的事情。因此,我将为您提供一个子集化的玩具示例:

dat <- data.frame(
 A = sample(letters[3:26],26,replace = TRUE)
 B = runif(26)
)

# Replaces everything in column B where column A == "a"
dat[dat$a == "c", "B"] <- 1

# dat$A == "c" returns a TRUE/FALSE vector, "B" returns column "B".

最佳做法是在子集化时始终使用 TRUE / FALSE 条件,以避免将来出现错误。您可以按行号进行子集化,但它总是会变得混乱。

请务必注意,您对 <<- 的使用会将您对变量的更改推送到父环境,超出您的函数范围。这可能会在未来导致意想不到的结果。最好提供您要更改的变量,然后在您的操作函数结束时再次 return 它。这样你就有了清晰的事件顺序。

myfun <- function(x,y) { 
  # ... do stuff to y
  return(y)
}

y <- myfun(x,y) 

最终更新

最后,关于删除不必要的列。典型的做法是在按名称(最佳做法)或参考编号(数据更改打破这一点)导入后删除它们。

ldata[c('col1','col2',...)] <- NULL # drop