我有一个很大的数据帧(250000行),“Row”和"Col“是列名。给定值为Row = a,Col =b的行,我希望找到值为Row = b,Col =a的相应行,并将一个值(列"normalised_weight")存储在一个空列(列"weight_ji")中。就目前而言,我的代码可以工作,但需要花费很长时间。有没有一种更有效的编码方式?
下面是我现在拥有的代码:
for (i in 1:nrow(data)){
a <- data[i,]$Row
b <- data[i,]$Col
data[i,]$weight_ji <- data[which(data$Col==a&data$Row==b),]$normalised_weight
}编辑
我尝试了所有三个答案,它们都有效,所以我比较了执行时间,如下所示:
library(dplyr)
set.seed(123)
data <-
data.frame(
a = 1:10,
b = 10:1,
normalizeweight = sample(1:100, 10, replace = T) / 100
)
start <- Sys.time()
result <- merge(data, data, by.x = c('a', 'b'), by.y = c('b', 'a'))
time1 <- Sys.time()-start
start <- Sys.time()
result <- data %>%
left_join(data, data, by = c("a" = "b", "b" = "a"))
time2 <- Sys.time()-start
start <- Sys.time()
result <- within(
data,
weight_ji <- normalizeweight[match(b, a)]
)
time3 <- Sys.time()-start似乎最快的方法是第三种解决方案。
但是如果数据帧有点不规则,比如:
data <-
data.frame(
a = c(1, 1, 1, 2, 2, 4, 4),
b = c(1, 2, 4, 1, 2, 1, 4),
normalizeweight = sample(1:100, 7, replace = T) / 100
)那么第三种解决方案就不再有效了。
此案例的第三个解决方案(重复)的更新为:
start <- Sys.time()
result <- within(
data,
weight_ji <- normalizeweight[order(a)][order(b, a)]
)
time4 <- Sys.time()-start在重复的情况下,这种解决方案仍然是最快的。
对于merge()解决方案:
为了避免有成千上万的".x“和".y”列(在我的数据集中,我有超过3列),我这样做了:
data <- merge(data, data[, c("Col", "Row", "normalised_weight")], by.x = c('Row', 'Col'), by.y = c('Col', 'Row'))%>%
dplyr::rename(normalised_weight=normalised_weight.x, weight_ji=normalised_weight.y)非常感谢你的帮助,真的很温馨!
发布于 2021-01-11 18:19:12
您可以尝试使用match对行进行索引,例如,
within(
data,
weight_ji <- normalizeweight[match(Col, Row)]
)或
within(
data,
weight_ji <- normalizeweight[order(a)][order(b, a)]
)发布于 2021-01-11 17:40:01
你可以对你的数据本身进行自连接。
set.seed(123)
data <- data.frame(Row = 1:5, Col = 5:1, normalizeweight = rnorm(5))
result <- merge(data, data, by.x = c('Row', 'Col'), by.y = c('Col', 'Row'))
result
# Row Col normalizeweight.x normalizeweight.y
#1 1 5 -0.5605 0.1293
#2 2 4 -0.2302 0.0705
#3 3 3 1.5587 1.5587
#4 4 2 0.0705 -0.2302
#5 5 1 0.1293 -0.5605其中normalizeweight.x是原始normalizeweight列,normalizeweight.y是weight_ji列。
发布于 2021-01-11 17:54:41
有了left_join,速度会更快。请确保您没有重复的观察结果。
library(dplyr)
set.seed(1234)
data <-
data.frame(
a = 1:10,
b = 10:1,
normalizeweight = sample(1:100, 10, replace = T) / 100
)
data %>%
left_join(data, data, by = c("a" = "b", "b" = "a"))注意:任何类似inner_join的命令都会删除(a,b)对没有匹配(b,a)的行。
https://stackoverflow.com/questions/65664096
复制相似问题