【问题标题】:Writing an R function that creates columns编写创建列的 R 函数
【发布时间】:2021-03-15 10:46:39
【问题描述】:

我想根据同一数据框的 Column CountryID 的内容向我的数据框 df 添加列。我让它工作了,但我有 60 条复制粘贴行。

df$Country1 <- ifelse(as.integer(df$CountryID == 1), 1, 0)
df$Country2 <- ifelse(as.integer(df$CountryID == 2), 1, 0)
df$Country3 <- ifelse(as.integer(df$CountryID == 3), 1, 0)
... 60 more lines

为了使代码更有条理,我想编写一个函数 createColumns,我只需要调用它,括号内的整个代码就会被执行。我最近的尝试没有创建任何列。 有谁知道如何解决这个问题?

createColumns <- function() {
df$Country1 <- ifelse(as.integer(df$CountryID == 1), 1, 0)
df$Country2 <- ifelse(as.integer(df$CountryID == 2), 1, 0)
df$Country3 <- ifelse(as.integer(df$CountryID == 3), 1, 0)
... 60 more lines
return(invisible())
}

【问题讨论】:

    标签: r function


    【解决方案1】:

    你需要返回新对象

    createColumns <- function(df) {
        df$Country1 <- ifelse(as.integer(df$CountryID == 1), 1, 0)
        df$Country2 <- ifelse(as.integer(df$CountryID == 2), 1, 0)
        df$Country3 <- ifelse(as.integer(df$CountryID == 3), 1, 0)
        ... 60 more lines
        df
    }
    

    然后这样使用它:

    df <- createColumns(df)
    

    您不能(轻松)修改 R 中的非本地对象,这是故意的:您不应该这样做。相反,像上面所做的那样明确分配。


    还有一些注意事项;例如,重复你写的内容 60 次应该是一个巨大的危险信号。重新考虑问题:您可能一开始不想要 60 列(相反,研究并使用 tidy data 的概念)但如果您真的这样做,您可能可以使用枢轴函数来替换这 60 行代码只需一行代码。

    此外,R 具有逻辑数据类型。这意味着,在几乎所有用例中,您都将分配 TRUEFALSE 而不是 1 和 0。所以,不要写

    ifelse(as.integer(df$CountryID == 1), 1, 0)
    

    你可以把它简化为

    df$CountryID == 1
    

    此外,as.integer 调用完全多余ifelse 需要一个逻辑参数,因此您当前的代码采用逻辑向量,将其显式转换为整数,结果被ifelseback转成逻辑向量。

    【讨论】:

    • 感谢您的快速帮助。就一个问题:为什么要在函数末尾再写一次df?没有它就行不通。只是好奇
    • @BlackPearl 一个函数返回其最后一个表达式的值——因为你想返回数据框本身,所以这就是最后一个。否则该函数将返回最后一个赋值的值,它只对应于最后一列的值。
    【解决方案2】:

    如果您想以更简单的方式获得所需的输出,可以尝试table + cbind,如下所示

    newCols <- as.data.frame.matrix(table(cbind(q = 1:nrow(df),df)))
    dfout <- cbind(df,`colnames<-`(newCols,paste0("Country",colnames(newCols))))
    

    这样

    > dfout
      countryID Country1 Country2 Country3
    1         1        1        0        0
    2         3        0        0        1
    3         1        1        0        0
    4         2        0        1        0
    5         1        1        0        0
    

    数据

    > dput(df)
    structure(list(countryID = c(1L, 3L, 1L, 2L, 1L)), class = "data.frame", row.names = c(NA, 
    -5L))
    

    【讨论】:

      猜你喜欢
      • 2021-03-06
      • 1970-01-01
      • 2019-02-11
      • 1970-01-01
      • 2021-12-07
      • 1970-01-01
      • 2022-01-12
      • 1970-01-01
      相关资源
      最近更新 更多