【问题标题】:How could I define an R data.table/data.frame column from a function parameter?如何从函数参数定义 R data.table/data.frame 列?
【发布时间】:2018-11-08 13:48:44
【问题描述】:

我在一个带有多个参数的 R 包中创建了一个函数。其中一个参数是 R data.table 的列名。

假设我想创建一个包含所有值42 的列。对于 R data.table dt,我会这样做:

dt[, column_name:=42]

对于 R data.frame,我会这样做:

df$column_name = 42

我希望函数将定义column_name 的东西作为参数。例如

调用的函数func
func(dt, col='hey')

hey 作为 data.table 列的新名称传递。

这是一个具体的例子

renamer = function(colname, dt){
    ## do calculations on dt
    dt[, colname:= 42]
}

如果我调用函数renamer(colname = 'foo', dt=dt),生成的列名仍将是colname,而不是我传递的值“foo”。

新列应该是字符串'foo'

我怎么能这样做?我也尝试过使用 R data.frame,或者尝试使用

setnames(dt, "oldname", "newname")

编辑:我认为应该澄清这个问题:

这是一个data.table:

> library(data.table)
> DT = data.table(ID = c("b","b","b","a","a","c"), a = 1:6, b = 7:12, c = 13:18)
> DT
   ID a  b  c
1:  b 1  7 13
2:  b 2  8 14
3:  b 3  9 15
4:  a 4 10 16
5:  a 5 11 17
6:  c 6 12 18

我想创建一个函数,使列的新名称成为用户传递给它的字符串。

例如

colnamer = function(newcolumname, datatable){
    ## do calculations on dt
    ## create a column with whatever string is passed via 'newcolumnname'
}

如果用户调用colnamer('foobar', DT),我希望结果是

> DT
   ID a  b  c  foobar
1:  b 1  7 13   ...
2:  b 2  8 14   ...
3:  b 3  9 15   ...
4:  a 4 10 16   ...
5:  a 5 11 17   ...
6:  c 6 12 18   ...

【问题讨论】:

  • 不太确定你想要什么?您想更改renamer 函数中colname 的列名还是更改colname 的内容?在后一种情况下,我认为这会起作用; dt[, get(colname) := 42]
  • @tstev 我希望将新列命名为用户在函数中传递的字符串。例如在上面的renamer(colname = 'foo', dt=dt) 中,新列将是foo
  • @tstev 我对get(colname) 的错误是Error in get(colname) : object 'foo' not found
  • 喜欢dt[[colname]] <- 42 ?
  • 我不是data.table 专家,但我认为renamer 中的行应该是dt[, (colname) := 42]

标签: r function dataframe data.table r-package


【解决方案1】:

编辑:更改为 OP 的新可重现示例,其中包含两个根据 OP 问题陈述起作用的建议;

library(data.table) 
DT <- data.table(ID = c("b","b","b","a","a","c"), 
                 a = 1:6, b = 7:12, c = 13:18)

colnamer1 <- function(newcolumname, datatable) {
  ## do calculations on dt
  ## create a column with whatever string is passed via 'newcolumnname'
  set(datatable, j = newcolumname, value = 42)
}

colnamer2 <- function(newcolumname, datatable) {
  ## do calculations on dt
  ## create a column with whatever string is passed via 'newcolumnname'
  dt[, (newcolumname) := 42]
}

colnamer1("name_me", DT)
colnamer2("name_me_too", DT)
DT
#    ID a  b  c name_me name_me_too
# 1:  b 1  7 13      42          42
# 2:  b 2  8 14      42          42
# 3:  b 3  9 15      42          42
# 4:  a 4 10 16      42          42
# 5:  a 5 11 17      42          42
# 6:  c 6 12 18      42          42

可能的data.frame 解决方案?虽然自从采用data.table 我的data.frame-ing 有点生疏了。对于data.frame,也许有更优雅的解决方案来解决您的问题。

df <- data.frame(ID = c("b","b","b","a","a","c"), 
                 a = 1:6, b = 7:12, c = 13:18)
df_colnamer <- function(name_me, df) {
  new_df <- df
  new_df[[name_me]] <- 42
  new_df
}
new_df <- df_colnamer("foo", df)
new_df
#   ID a  b  c foo
# 1  b 1  7 13  42
# 2  b 2  8 14  42
# 3  b 3  9 15  42
# 4  a 4 10 16  42
# 5  a 5 11 17  42
# 6  c 6 12 18  42

【讨论】:

  • 谢谢,这是有道理的。我想知道——如果它是一个 data.frame,怎么做?除了将其转换为 data.table...
  • @ShanZhengYang,然后@Moody_Mudskipper 的建议会奏效。但是data.table的优势在于它可以在内存中通过引用来完成,而无需创建副本。
  • colnamer2 中有错字。应该是datatable[, (newcolumname) := 42]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-10
  • 2021-01-13
  • 1970-01-01
  • 1970-01-01
  • 2010-12-17
  • 1970-01-01
相关资源
最近更新 更多