【问题标题】:Loop of a loop in RR中的循环循环
【发布时间】:2012-01-11 10:13:26
【问题描述】:

这是我的问题:我有两个不同的数据框(A 和 B)。每个数据框的列是一个地理区域,行数据是一个区域的物种。我需要将数据名 A 的位置 1 的物种列表与数据框 B 的所有位置的物种列表相交。为此,我编写了一个这样的循环:

res<-list()
for(i in 1:length(B)) {intersect(A[1], B[i])->res[[i]]
}

现在我必须对 A 的位置 2,3,4,5,6,..... 重复相同的循环,也就是说我必须将 A 的所有位置与 A 的所有位置相交B.

谢谢。

【问题讨论】:

  • 欢迎来到 SO。如果您提供示例数据,问题会更容易回答。

标签: r loops


【解决方案1】:

这是使用lapply() 的嵌套循环的类似方法。

如果您有一个大型数据集,与使用循环相比,使用 lapply() 可能会大大提高您的速度。 R中循环比较慢,建议尽可能使用the *apply family中的向量化函数。

我将通过一个示例进行演示,您也许可以将其调整为您的数据集。

首先,我们创建一个名为 df 的示例 3x3 数据框,列有 abc,行有 def

> df <- data.frame(a = sample(3), b = sample(3), c = sample(3))
> rownames(df) <- c('d','e','f')

让我们看看df及其转置t(df)

> df
  a b c
d 3 1 3
e 1 3 1
f 2 2 2

> t(df)
  d e f
a 3 1 2
b 1 3 2
c 3 1 2

假设我们想要intersect dft(df) 的列向量。我们现在使用嵌套的lapply() 语句在来自df 和转置t(df) 的列向量上运行intersect()

> result <- lapply(df, function(x) lapply(as.data.frame(t(df)), function(y) intersect(x,y)))

结果是list(),显示交集结果:

> is.list(result)
[1] TRUE

> print(result)
$a
$a$d
[1] 3 1

$a$e
[1] 3 1

$a$f
[1] 2


$b
$b$d
[1] 1 3

$b$e
[1] 1 3

$b$f
[1] 2


$c
$c$d
[1] 3 1

$c$e
[1] 3 1

$c$f
[1] 2

让我们再看看dft(df),看看如何读取这些结果:

> df
  a b c
d 3 1 3
e 1 3 1
f 2 2 2

> t(df)
  d e f
a 3 1 2
b 1 3 2
c 3 1 2

让我们看看df$at(df)$dt(df)$et(df)$f相交:

$a
$a$d
[1] 3 1

与向量ad 相交:{3,1,2}^{3,1,3} = {3,1}

$a$e
[1] 3 1

同样,使用向量 ae{3,1,2}^{1,3,1} = {3,1}

$a$f
[1] 2

最后,使用向量 af{3,1,2}^{2,2,2} = {2}

result 中的其他项目如下。

要将其扩展到您的数据集,请将您的数据框列视为localities,将转置数据框列视为您的物种。然后使用lapply(),如上图。


要分解嵌套的lapply() 语句,请从内部lapply() 开始:

lapply(as.data.frame(t(df)), function(y) ... )

这意味着t(df) 中的每个列向量——$d、$e 和$f 列——都由function(y) 中的变量y 表示。我们稍后会回到...

现在我们看看外层lapply()

lapply(df, function(x) ... )

这意味着df 中的每个列向量($a、$b 和 $c 列)都由 function(x) 中的变量 x 表示。

现在让我们解释一下...

外部...x 的任何函数——这可以是length()sum() 等,甚至是另一个lapply()。内部lapply() 有自己的函数和变量名y,因此内部... 可以在xy 上运行函数。

这就是我们所做的:对于df 中的每个列向量,我们对该df-vector 和转置t(df) 中的每个列向量运行一个函数。在我们的示例中,我们将在xy 上运行的函数是intersect()

> result <- lapply(df, function(x) lapply(as.data.frame(t(df)), function(y) intersect(x,y)))

【讨论】:

  • 这是一个非常有趣的过程。这是我尝试的第一种方式,但直到现在我才能理解 lapply 的工作原理。解释非常有用。谢谢
【解决方案2】:

很难完全理解您想要获得的结果。但是,如果我猜对了您的需求,下面的代码将满足您的需求。这段代码当然可以进一步优化以提高速度,因为对于大数据集它可能工作得不会太快。

res <- list()
for (i in 1:ncol(A)) {
  res[[i]] <- list()
  for (j in 1:ncol(B)) {
    res[[i]][[j]] <- intersect(A[,i], B[,j])
  }
}

要访问结果,您可以使用

res[[column_index_in_A]][[column_index_in_B]]

【讨论】:

    【解决方案3】:

    以下是对您的数据的疯狂猜测:

    A <- data.frame(
      London     = c(TRUE, TRUE, FALSE),
      Manchester = c(FALSE, TRUE, FALSE),
      Birmingham = c(TRUE, FALSE, TRUE),  
      row.names  = c("rats", "mice", "foxes")
    )
    
    B <- data.frame(
        London     = c(TRUE, FALSE, FALSE),
        Manchester = c(TRUE, TRUE, TRUE),
        Birmingham = c(TRUE, TRUE, FALSE),
        row.names  = c("rats", "mice", "foxes")    
    )
    
    
    > A
          London Manchester Birmingham
    rats    TRUE      FALSE       TRUE
    mice    TRUE       TRUE      FALSE
    foxes  FALSE      FALSE       TRUE
    > B
          London Manchester Birmingham
    rats    TRUE       TRUE       TRUE
    mice   FALSE       TRUE       TRUE
    foxes  FALSE       TRUE      FALSE
    

    在这种情况下,要在两个数据集中找到存在于同一位置的物种,您只需要

    as.matrix(A) & as.matrix(B)
    

    【讨论】:

    • 谢谢,但我需要将注意力集中在动物列表的交集上,因为我需要计算相似指数
    猜你喜欢
    • 2022-11-11
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 2023-02-21
    • 2020-08-29
    • 2021-06-29
    • 1970-01-01
    相关资源
    最近更新 更多