【问题标题】:creating functions with arguments as column names创建以参数为列名的函数
【发布时间】:2018-10-09 21:17:25
【问题描述】:

我正在尝试创建一个函数,它将在一列的值与另一列的值之间进行成对比较,并根据这些值创建一个新向量。我无法弄清楚如何允许两个参数成为可以更改的列名,并且可以在另一组列上使用该函数。 具体情况是有四列彩色带标签用于父鸟(pbc1...pbc4),另外四列用于其小鸡(obc1...obc4)。带列是字符列,例如“G”“PG”“B”等。 这是我的函数第一部分的代码,我将在运行后将其扩展为包括所有成对比较:

colourdistance1 <- function(df, refcoldistdf, pbc, obc){
    n <- length(pbc)
    coldist1 <- rep(NA,n)
    for(i in 1:n){
        if(pbc[i]==obc[i]){
            coldist1[i] <- 0
         } else if(pbc[i]=='M'|obc[i]=='M'){
             coldist1[i] <- NA
         } else if(pbc[i]=='G'& obc[i]=='PG'| obc[i]=='G'& pbc[i]=='PG'){
             coldist1[i] <- refcoldistdf[2,2]
         } else {
             coldist1[i] <- NA
         }
    }
}

p1o1 <- colourdistance1(bd_df, refcoldistdf,pbc = pbc1, obc = obc1)

这个调用只是返回对象 p1o1 为 NULL 我也试过:

colourdistance1 <- function(df, refcoldistdf, pbc, obc){
    n <- length(pbc)
    coldist1 <- rep(NA,n)
    for(i in 1:n){
        if(df$pbc[i]==df$obc[i]){
            coldist1[i] <- 0
        } else if(df$pbc[i]=='M'|df$obc[i]=='M'){
            coldist1[i] <- NA
        } else if(df$pbc[i]=='G'& df$obc[i]=='PG'| df$obc[i]=='G'& df$pbc[i]=='PG') { 
            coldist1[i] <- refcoldistdf[2,2]
        } else {
            coldist1[i] <- NA
        }
    }
}

但这只是给出了这个错误:

Error in if (df$pbc[i] == df$obc[i]) { : argument is of length zero

我已经尝试了函数外的所有代码,插入列名和索引号以及 df 名称,一切正常。这让我觉得我有一个函数参数没有按照我的意图连接到函数代码的问题。 任何帮助将不胜感激!

可重现的测试数据:

pbc1 <- c('B','W','G','R')
obc1 <- c('Y','W','PG','FP')
pbc2 <- c('W','W','W','M')
obc2 <- c('M','W','R','R')
pbc3 <- c('W','K','FP','K')
obc3 <- c('G','PG','B','PB')
pbc4 <- c('K','K','B','M')
obc4 <- c('K','PG','W','M')
testbanddf <- cbind(pbc1,obc1,pbc2,obc2,pbc3,obc3,pbc4,obc4)
testrefcoldist <- diag(11)

【问题讨论】:

  • 您不能使用 $ 引用传递给函数的参数 - 您需要使用 [[[。因此,您需要 df[[pbc]] 而不是 df$pbc,您可以在其中调用函数和参数,例如 colourdistance1(df, pbc="colname")

标签: r


【解决方案1】:

所以有很多 cmets 要做,但首先,你可以试试这个:

pbc1 <- c('B','W','G','R')
obc1 <- c('Y','W','PG','FP')
pbc2 <- c('W','W','W','M')
obc2 <- c('M','W','R','R')
pbc3 <- c('W','K','FP','K')
obc3 <- c('G','PG','B','PB')
pbc4 <- c('K','K','B','M')
obc4 <- c('K','PG','W','M')
testbanddf <- data.frame(pbc1,obc1,pbc2,obc2,pbc3,obc3,pbc4,obc4)
testrefcoldist <- diag(11)

colourdistance1 <- function(df, refcoldistdf, pbc, obc){
    n <- nrow(df)
    coldist1 <- rep(NA,n)

    pbc <- df[[pbc]]
    obc <- df[[obc]]

    for(i in 1:n){
        if(pbc[i]==obc[i]){
            coldist1[i] <- 0
        } else if(pbc[i]=='M'|obc[i]=='M'){
            coldist1[i] <- NA
        } else if(pbc[i]=='G'& obc[i]=='PG'| obc[i]=='G'& pbc[i]=='PG'){
            coldist1[i] <- refcoldistdf[2,2]
        } else {
            coldist1[i] <- NA
        }
    }
    coldist1
}

colourdistance1(testbanddf, testrefcoldist,pbc = "pbc1", obc = "obc1")
  1. cbind() 创建矩阵,而不是数据框。您使用函数 data.frame() 创建数据框。
  2. 最简单的方法是将参数pbcobc 设为字符,表示列名。
  3. 使用$ 引用数据框列在交互工作时很有用,但在编写函数并且事先不知道列的名称时就不那么有用(正如您所发现的)。在这种情况下,您可以使用[[,并可以按名称或位置选择它们。
  4. 您编写的函数未明确返回 coldist1

【讨论】:

  • 感谢您的意见,尝试了所有的调整,它仍然给出的参数是长度为零错误
  • @JessicaHall 如果你准确地运行我的代码,它不会产生那个错误。如果您仍然收到该错误,则表示您正在运行您自己的代码的未完全修改版本,该版本尚未完全纳入我提出的观点。
猜你喜欢
  • 2021-07-30
  • 2022-07-26
  • 2014-12-22
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-10
相关资源
最近更新 更多