首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >R在具有值a_i和b_i的行上加快循环速度,其中我们选择a= b_i和b= a_i的行

R在具有值a_i和b_i的行上加快循环速度,其中我们选择a= b_i和b= a_i的行
EN

Stack Overflow用户
提问于 2021-01-11 17:18:44
回答 3查看 61关注 0票数 1

我有一个很大的数据帧(250000行),“Row”和"Col“是列名。给定值为Row = a,Col =b的行,我希望找到值为Row = b,Col =a的相应行,并将一个值(列"normalised_weight")存储在一个空列(列"weight_ji")中。就目前而言,我的代码可以工作,但需要花费很长时间。有没有一种更有效的编码方式?

下面是我现在拥有的代码:

代码语言:javascript
运行
复制
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
  }

编辑

我尝试了所有三个答案,它们都有效,所以我比较了执行时间,如下所示:

代码语言:javascript
运行
复制
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

似乎最快的方法是第三种解决方案。

但是如果数据帧有点不规则,比如:

代码语言:javascript
运行
复制
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
  )

那么第三种解决方案就不再有效了。

此案例的第三个解决方案(重复)的更新为:

代码语言:javascript
运行
复制
start <- Sys.time()
result <- within(
  data,
  weight_ji <- normalizeweight[order(a)][order(b, a)]
)
time4 <- Sys.time()-start

在重复的情况下,这种解决方案仍然是最快的。

对于merge()解决方案:

为了避免有成千上万的".x“和".y”列(在我的数据集中,我有超过3列),我这样做了:

代码语言:javascript
运行
复制
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)

非常感谢你的帮助,真的很温馨!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-01-11 18:19:12

您可以尝试使用match对行进行索引,例如,

代码语言:javascript
运行
复制
within(
  data,
  weight_ji <- normalizeweight[match(Col, Row)]
)

代码语言:javascript
运行
复制
within(
  data,
  weight_ji <- normalizeweight[order(a)][order(b, a)]
)
票数 2
EN

Stack Overflow用户

发布于 2021-01-11 17:40:01

你可以对你的数据本身进行自连接。

代码语言:javascript
运行
复制
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.yweight_ji列。

票数 2
EN

Stack Overflow用户

发布于 2021-01-11 17:54:41

有了left_join,速度会更快。请确保您没有重复的观察结果。

代码语言:javascript
运行
复制
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)的行。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65664096

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档