根据匹配仅更新数据框的某些值
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 个值 chrom
、position
和 freq
,而不仅仅是最后一次迭代。
我觉得这应该很简单,但我对 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
我正在尝试根据匹配更新 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 个值 chrom
、position
和 freq
,而不仅仅是最后一次迭代。
我觉得这应该很简单,但我对 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