【问题标题】:apply() function not working on individual rowsapply() 函数不适用于单个行
【发布时间】:2019-10-12 06:59:14
【问题描述】:

我编写了一个函数,用于从大矩阵(“c.mat”)中为 data.frame(“df.1”)中的每一行提取数据。 data.frame 中有一个索引行(“df.1$hour”),对应于矩阵中的相关列。矩阵和 data.frame 之间的行数相等,因此函数运行:

assignUV.FUN <- function(df, mat){
  num=df$hour
  value = mat[as.numeric(rownames(df)),num]
  return(value)
}

很简单。但是,当使用 apply 为每一行运行时:

df.1 <- data.frame(hour= round(runif(10,1,100)), x = seq(1,10, length=10))
c.mat <- matrix(runif(1000,1,5), nrow=10)

try <- apply(df.1, 1, assignUV.FUN, mat = c.mat, df=df.1)

我得到错误:

Error in FUN(newX[, i], ...) : unused argument (newX[, i])

我确定这里存在冲突,我两次调用 data.frame,一次从 assignUV.FUN 函数内部,一次使用 apply,但我不知道为什么这不起作用。

有什么想法吗?如果我只在一行上运行它就可以正常工作:

assignUV.FUN(df = df.1[1,], mat=c.mat)

【问题讨论】:

    标签: r dataframe matrix apply


    【解决方案1】:

    如果我对您的理解正确,您希望根据hour 列中的值对df.1 中的每一行进行子集c.mat。我不认为apply 是这里的最佳选择,因为您想通过行索引和列索引对其进行子集化。 apply 传递行的值,而不是子集所需的索引。 apply 系列的一种选择是使用 mapply

    mapply(function(x, y) c.mat[x, y], seq_len(nrow(df.1)), df.1$hour)
    #[1] 2.472 3.980 3.654 4.868 4.204 3.320 4.191 3.296 1.016 4.353
    

    或者矢量化方法是

    c.mat[cbind(1:nrow(df.1), df.1$hour)]
    #[1] 2.472 3.980 3.654 4.868 4.204 3.320 4.191 3.296 1.016 4.353
    

    要详细了解它为何在您单独申请一行而不是在您使用 apply 时起作用,请注意,当您对一行进行子集化时,它仍然是一个带有标题的单行数据框。

    df.1[1, ]
    #  hour x
    #1   31 1
    
    class(df.1[1, ])
    #[1] "data.frame"
    

    所以当你在assignUV.FUN 函数中执行df$hour 时,你会得到一个值

    df.1[1, ]$hour
    #[1] 31
    

    但是,apply 并非如此

    apply(df.1[1, ], 1, class)
    #        1 
    #"numeric" 
    

    如果你尝试提取价值

    apply(df.1[1, ], 1, function(x) x$hour)
    

    x$hour 中的错误:$ 运算符对原子向量无效

    您可以通过使用位置而不是名称来解决上述问题

    apply(df.1[1, ], 1, function(x) x[1])
    #31 
    

    但这为您提供了从c.mat 到子集的列,而不是行。

    数据

    set.seed(100)
    df.1 <- data.frame(hour= round(runif(10,1,100)), x = seq(1,10, length=10))
    c.mat <- matrix(runif(1000,1,5), nrow=10)
    

    【讨论】:

    • 你已经明白了,这已经完美地回答了这个问题,谢谢。我明白为什么 apply 在这种情况下不合适。
    【解决方案2】:

    Ronak 的矢量方法是可行的方法,但我希望这可以提供指导。 apply 不会将data.frame 传递给FUN,而是传递一个向量,所以你可以试试,

    assignUV.FUN <- function(DF, mat){
      num=DF[1]
      value = mat[DF[2],num]
      return(value)
    }
    
    try <- apply(df.1, 1, assignUV.FUN, mat = c.mat)
    

    没有必要将FUN 的所有参数传递给apply,我只传递了c.mat,因为它没有被“循环”。另外,我尽量避免命名data.frames df,因为R 已经有一个名为df 的函数(F 分布的密度)。

    【讨论】:

    • 谢谢Simon,这对正确理解apply的使用很有帮助。考虑到我遇到的错误,apply 将传递一个向量而不是 data.frame 是有道理的。我也永远不会将我的数据框称为 df 但这只是为了一个可重复的示例。
    猜你喜欢
    • 1970-01-01
    • 2016-04-29
    • 2012-02-12
    • 2022-06-19
    相关资源
    最近更新 更多