【问题标题】:Apply function across mulitple columns in R跨 R 中的多列应用函数
【发布时间】:2016-01-19 19:10:49
【问题描述】:

我正在尝试在 R 中编写一个简化的函数来比较矩阵中的多个列。在 R 中执行此操作的最佳方法是什么?最有可能使用应用。

我已经多次看到这个问题出现了,但对于编写此问题的最佳方式存在一些相互矛盾的观点。

for ( j in 2:ncol(net) )
{
    for ( i in 1:nrow(net) )
    {
            net[i,j] <- min(net[i,j],net[i,1])
    }
}

一个矩阵的结束输出如下

     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    2    2    3
[3,]    3    2    3

应该是

     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    2    3

【问题讨论】:

  • 这让我读起来很困惑,因为i 普遍用于索引行;和j 列。特别是,您将在帮助文件help("[") 中看到这些名称
  • 我现在已经在原文中编辑了这个,并用一个例子更新了这个问题。
  • 您显示的输入不是data.frame。这是一个matrix。所以,请不要将其他人与您的描述混淆。
  • 现在重新编辑了措辞
  • @user2065472 您愿意接受给定的答案之一吗? ...点击投票旁边的。 stackoverflow.com/help/accepted-answer

标签: r loops lapply sapply


【解决方案1】:

我们可以unlist除第一列(net[-1])之外的“网络”列,将第一列复制为与unlisted列相同的长度,并使用pmin得到最小值vectors 的对应元素。

pmin(unlist(net[-1], use.names=FALSE), net[,1][row(net[-1])])
#[1] 2 2 7 5 2 2 2 6 5 3 2 1 0 5 1

如果我们需要lapply 解决方案,

unlist(lapply(net[-1], function(x) pmin(x, net[,1])), use.names=FALSE)

使用 OP 的 for 循环

for ( i in 2:ncol(net) ){
   for ( j in 1:nrow(net) ){
     print(min(net[j,i],net[j,1]))
   }
 }
#[1] 2
#[1] 2
#[1] 7
#[1] 5
#[1] 2
#[1] 2
#[1] 2
#[1] 6
#[1] 5
#[1] 3
#[1] 2
#[1] 1
#[1] 0
#[1] 5
#[1] 1

更新

正如 OP 提到的,这没有给出预期的输出,尝试使用 OP 帖子中显示的新数据

net <- cbind(1:3, 2, 3)

cbind(net[,1],pmin(unlist(net[,-1], use.names=FALSE), 
           net[,1][row(net[,-1])]))
#      [,1] [,2] [,3]
#[1,]    1    1    1
#[2,]    2    2    2
#[3,]    3    2    3

数据

set.seed(24)
net <- as.data.frame(matrix(sample(0:9, 4*5, replace=TRUE), ncol=4))

【讨论】:

  • 这不是只给出列的最小值而不是特定两个单元格比较的最小值,即我将第一列/行值的最小值与每一行进行比较/之后的列值?
  • @user2065472 最好提供一个可重现的示例。您可以尝试更新的解决方案吗?
  • 如果有三列,这将不起作用。矩阵子集将产生越界错误。试试net &lt;- as.data.frame(matrix(sample(0:9, 3*5, replace=TRUE), ncol=3))
  • @PierreLafortune 我认为net[,1] 应该让它工作。
  • 是的,这将避免方法分派。
【解决方案2】:

如果没有NAs 你可以这样做

net <- head(airquality, 4) # example data
for (j in 1:nrow(net)) net[j, net[j,]>net[j,1]] <- net[j,1]
net

【讨论】:

  • 这个解决方案给出了预期的结果,并且比我的双循环快得多,但我仍然觉得可以加快速度(我不太确定)......
  • IMO 在 R 中不可能显着加速,因为在较低级别上,操作现在是矢量化的。编码当然可以更紧凑,但我想那将是循环隐藏。
【解决方案3】:

这是一个带有 sapplyifelse(矢量化,哇)的版本,它可能更快,并且以可预测的方式处理 NA 值:

sapply(X = seq(to = ncol(x = net)), FUN = function(j){
  net[,j] <- ifelse(test = net[,1] < net[,j], yes = net[,1], no = net[,j])
})

一些样本数据

net <- head(airquality)
net
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6

结果:

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]   41   41  7.4   41    5    1
[2,]   36   36  8.0   36    5    2
[3,]   12   12 12.0   12    5    3
[4,]   18   18 11.5   18    5    4
[5,]   NA   NA   NA   NA   NA   NA
[6,]   28   NA 14.9   28    5    6

注意:我几乎指定了所有参数名称,因为我发现这会使大多数代码更快。如果你不在乎时间,更简单的[可能更易读]版本:

sapply(seq(ncol(net)), function(j){
    net[,j] <- ifelse(net[,1] < net[,j], net[,1], net[,j])
})

【讨论】:

    猜你喜欢
    • 2021-07-13
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    相关资源
    最近更新 更多