简化双for循环

简化双for循环,r,for-loop,matrix,R,For Loop,Matrix,我有两个矩阵。矩阵A有14个变量(但在本练习中我只对五个变量感兴趣),矩阵B有五个变量。矩阵A有250000个观测值,矩阵B有23000个观测值。变量是非数字字符(文本) 我的目标是用矩阵B第4列和第5列中的信息填充矩阵A的第9列和第10列,前提是矩阵A的第1列、第2列和第8列等同于矩阵B的第1列、第2列和第3列 我写的代码是双for循环,运行大约需要10天。我正在寻找一种方法来简化代码,使其更高效,运行速度更快(最好在几个小时内) 代码如下: for (i in 1:nrow(matr

我有两个矩阵。矩阵A有14个变量(但在本练习中我只对五个变量感兴趣),矩阵B有五个变量。矩阵A有250000个观测值,矩阵B有23000个观测值。变量是非数字字符(文本)

我的目标是用矩阵B第4列和第5列中的信息填充矩阵A的第9列和第10列,前提是矩阵A的第1列、第2列和第8列等同于矩阵B的第1列、第2列和第3列

我写的代码是双for循环,运行大约需要10天。我正在寻找一种方法来简化代码,使其更高效,运行速度更快(最好在几个小时内)

代码如下:

    for (i in 1:nrow(matrix_b)) {
      for (j in 1:nrow(matrix_a)) {
        if (matrix_a[j,1]==matrix_b[i,1]) {
          if (matrix_a[j,2]==matrix_b[i,2]) {
            if (matrix_a[j,8]==matrix_b[i,3]) {
              matrix_a[j,9]<-matrix_b[i,4]
              matrix_a[j,10]<-matrix_b[i,5]
            }
          }
        }
      }
    }
在这种情况下,代码应在矩阵A的单元格[1,9]中插入“Aldi”,在单元格[1,10]中插入“CFO”,因为矩阵A中的单元格[1,1]、[1,2]和[1,8]与矩阵B中的单元格[1,1]、[1,2]和[1,3]相同

如果数据看起来像这样(第2列中的日期不同),代码不应该做任何事情;i、 例如,将矩阵A中的[1,9]和[1,10]单元格保持原样

    # Matrix A
          [,1]   [,2]         [,8]            [,9]       [,10]
    [1,]   Z10   15 Dec 2013   Rocko Large     NA         NA


    # Matrix B
          [,1]   [,2]         [,3]            [,4]       [,5]
    [1,]   Z10   11 Nov 2012   Rocko Large     Aldi       CFO

这里有一种方法可以完全避免循环,而是使用连接来达到相同的效果:

set.seed(1)

# Create some fake data with the given dimensions
matrix_a <- matrix(sample(letters, 14 * 250000, replace = T), ncol = 14)
matrix_b <- matrix(sample(letters, 5 * 23000, replace = T), ncol = 5)

library(dplyr)

# Convert matrices to data frames
df_a <- as_tibble(matrix_a)
df_b <- as_tibble(matrix_b)

# Simplify df_b so that multiple rows from df_b don't match the same row
# in df_a: this is implied by the loop in the question, and isn't necessary
# to do for the real data, if the condition holds.
df_b <- df_b %>% 
  distinct(V1, V2, V3, .keep_all = T)

new <- df_a %>% 
  # join columns from b to a that match on the specified variables
  left_join(df_b %>% rename_all(~ paste0("b_", .)),
            by = c(V1 = "b_V1", V2 = "b_V2", V8 = "b_V3")) %>%
  # if there was a match in b, replace value in a with the value from b
  mutate(
    V9  = if_else(!is.na(b_V4), b_V4, V9),
    V10 = if_else(!is.na(b_V5), b_V5, V10)
  ) %>% 
  # drop the added columns from b
  select(-starts_with("b_"))

使用数据表需要几秒钟。 我可以在这里给大家举个例子:

rm(list = ls())

A = replicate(14, round(rnorm(250000),digits = 2))
B = replicate(5,round(rnorm(250000),digits = 2))
只是创建两个矩阵

library(data.table)
DTA <- setDT(as.data.frame(A))
colnames(DTA) <- paste0("A",seq(dim(DTA)[2]))
DTB <- setDT(as.data.frame(B))
colnames(DTB) <- paste0("B",seq(dim(DTB)[2]))

DT <- cbind(DTA,DTB)
语法是DT[i,j,by]。列相等的条件在括号的第一部分中,在第二部分中,通过以下方式设置值:=

它将以同样的方式处理文本或因子


希望对您有所帮助

请提供一个Hi@docendosicmus,非常感谢您的评论。我举了一个例子。我希望这能有所帮助。问题中的矩阵有不同的行数(250000和23000),所以你不能只
cbind
;他们将不得不加入。我确实喜欢
data.table
方法,但是对于这样的问题,语法非常简洁!你好,丹尼斯,非常感谢你的回复。不幸的是,我无法下载“data.table”包。我收到以下错误消息:有一个二进制版本可用,但源版本更高:二进制源需要编译数据。表1.10.4-2 1.10.4-3将安装真正的二进制文件,正在尝试安装中的URL“”警告。软件包:无法打开URL“”:HTTP状态为“404未找到”下载文件中的错误(url,destfile,method,mode=“wb”,…):无法在install.packages中打开url“”警告:下载包“data.table”失败(链接太长,无法包含在单个注释中)我使用的是RStudio版本1.1.383。这可能是我无法下载该软件包的原因吗?您好。很抱歉,我不了解矩阵的行号不同。我将尝试提出其他解决方案。我使用的是与您相同版本的R studio。我不知道您为什么不能下载该软件包。如果有一个“更新加入"在
dplyr
中,对于这样的场景,而不是必须
左加入
变异
。非常感谢您的回复,@Mikko Marttila!我尝试运行代码,但不幸的是,我收到了以下错误消息:警告消息:1:Column
V1
/
b\u V1
在j的左和右上具有不同的属性oin 2:Column
V2
/
b_V2
在join的LHS和RHS上有不同的属性,您认为我可以如何解决这个问题?抱歉我的第一条评论不准确!如果我自己运行您的代码,它运行得非常好,速度惊人。但是如果我尝试在真实数据上运行它(使用以df_a%%>%开头的最后一个函数),我得到了声明的错误消息。我一定是做错了什么,但无法找出原因。这只是一条警告消息,您仍然应该得到正确的结果。这只是说数据集中的第1列和第2列具有不同的属性(即元数据)。如果您对此感到担忧,请继续并在您的问题中发布
lappy(df_a,attributes)
lappy(df_b,attributes)
的结果,这样我们就可以看到不同之处。
rm(list = ls())

A = replicate(14, round(rnorm(250000),digits = 2))
B = replicate(5,round(rnorm(250000),digits = 2))
library(data.table)
DTA <- setDT(as.data.frame(A))
colnames(DTA) <- paste0("A",seq(dim(DTA)[2]))
DTB <- setDT(as.data.frame(B))
colnames(DTB) <- paste0("B",seq(dim(DTB)[2]))

DT <- cbind(DTA,DTB)
DT[A1 == B1 & A2 == B2 & A3 == B8, A9 := B4]
DT[A1 == B1 & A2 == B2 & A3 == B8, A10 := B5]