在不正确的调用中传递给函数的各种参数

时间:2018-09-24 21:50:52

标签: r

一般问题

我想更改在lapply / sapply(或mapply?)调用中传递给函数的其他参数。一般情况下,知道如何执行此操作将非常高兴。但是,如果有问题,出于我的特定目的,我正在尝试将其合并到自定义函数中。 (因此希望它可以扩展)。

问题的具体示例

假设我有以下数据框:

df <- data.frame(column1 = letters[1:4], 
             column2 = LETTERS[1:4], 
             column3 = 1:4, 
             stringsAsFactors = FALSE)

作为一个例子,我想将column1和column2转换为因子,每个因子具有不同的级别。我可能会注意到这样的列和级别:

# Columns in df I want to apply the factor() function to.

     cols <- c("column1", "column2")

# Desired levels for column1

     column1_lvl <- c(letters[1:5])

# Desired levels for column2

     column2_lvl <- c(LETTERS[1:6])

请注意,我为列指定了两个单独的级别,每个级别都比df中存在的级别更多。这是改变论点的动机。现在,我测试了lapply调用,而没有将level参数的参数更改为factor:

     df[cols] <- lapply(df[,cols], factor)

这可以成功地将那些列转换为因子。我将df重新定义为下一步的原始结构。现在,我想为每个列指定级别。在?lapply中,它表示您可以将其他参数传递给FUN,但没有指定如何在X中的每个向量上改变这些参数。尝试使用 one 实例,我可以这样写:

     df["column1"]<- factor(df[,"column1"], levels = column1_lvl)

这有效。但是现在我想抽象levels参数。不幸的是,这是行不通的,因为无论您为levels分配了什么,R都会尝试将该参数用于X中向量的 each

理想情况下,类似以下内容的方法将起作用。 以下是我希望可以按照我想要的方式工作的伪代码,但并非如此

     df[cols] <- lapply(df[,cols], factor, level = list(column1_lvl, column2_lvl))

我尝试过的事情

我无法找到许多资源来解释我如何能够做到这一点。也许,我不知道需要做什么。 This post对我有所帮助,但是我想知道是否有办法创建自己的factor函数。

此外,this person's answer回答了他们自己的问题,促使我结识了mapply。尽管我已经阅读了?mapply的文档,并跟随了一些教程,但仍无法弄清楚。在那方面,我尝试了以下代码(出于我的目的)不起作用:

     col_levels <- list(column1_lvl, column2_lvl)
     df[cols] <- mapply(factor, df[,cols], MoreArgs = col_levels)

SessionInfo

> sessionInfo()
R version 3.5.1 (2018-07-02)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252    LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                           LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] compiler_3.5.1 tools_3.5.1    yaml_2.1.19  

最终想法

我可能很难知道要搜索什么。如果您能够指出正确的方向,我总是愿意亲自解决问题。任何其他资源都值得欢迎。

先谢谢了!

1 个答案:

答案 0 :(得分:3)

我们可以使用Map来更改列levelslist中相应的'lvl'对象

df[cols] <- Map(function(x, y) factor(x, levels = y),
             df[cols], list(column1_lvl, column2_lvl))

并检查列的levels

lapply(df[cols], levels)
#$column1
#[1] "a" "b" "c" "d" "e"

#$column2
#[1] "A" "B" "C" "D" "E" "F"

正如OP提到的使用lapply解决此问题的方法一样,使用lapply的一种选择是遍历序列,然后将数据和相应的“ lvls” list子集化

lvls_lst <- list(column1_lvl, column2_lvl)
df[cols] <- lapply(seq_along(lvls_lst), function(i) 
         factor(df[cols][[i]], levels = lvls_lst[[i]]))

注意:在这两种情况下,我们都需要明确指定levels