在需要更改的变量上使用for()

时间:2017-06-13 20:30:01

标签: r for-loop data.table

我希望能够使用for()循环来自动执行在修改它们的许多变量上运行的相同操作。

这是最简单的设计示例:

varToChange = list( 1:10, iris$Species[1:10], letters[1:10]) # assume that it has many more than just 3 elements
varToChange
for (i in varToChange ) {
  if (is.character(y)) i <- as.integer(as.ordered(i))
  if (is.factor(y)) i <- as.integer(i)
}
varToChange # <-- Here I want to see my elements as integers now

这是让我回答这个问题的实际例子 - 来自:Best way to plot automatically all data.table columns using ggplot2

在以下功能中

f <- function(dt, x,y,k) {
  if (is.numeric(x)) x <-  names(dt)[x]
  if (is.numeric(y)) y <-  names(dt)[y]
  if (is.numeric(k)) k <-  names(dt)[k]

 ggplot(dt, aes_string(x,y, col=k)) + geom_jitter(alpha=0.1)
}
f(diamonds, 1,7,2)

而不是像程序员那样残酷地重复相同的行,我宁愿有一个循环来为我重复这一行。 像这样的东西:

for (i in c(x,y,k)) {
  if (is.numeric(i)) i <-  names(dt)[i]
 }

在C / C ++中,这可以使用指针完成。在R - 这一切都可能吗?

更新:非常好的想法使用下面的地图。但是它不适用于此示例

getColName <- function(dt, x) { 
  if (is.numeric(x)) { 
    x <-  names(dt)[x]
  }  
  x  
}

f<- function(dt, x,y,k) {
  list(x,y,k) <- Map(getColName, list(x,y,k), dt)
  # if (is.numeric(x)) x <-  names(dt)[x]
  # if (is.numeric(y)) y <-  names(dt)[y]
  # if (is.numeric(k)) k <-  names(dt)[k]

  ggplot(dt, aes_string(x,y, col=k)) + geom_jitter(alpha=0.1)
}
f(diamonds, 1,7,2) # Brrr..

2 个答案:

答案 0 :(得分:3)

不需要for循环,只需在每个列表项上映射一个函数

varToChange = list( 1:10, iris$Species[1:10], letters[1:10])     
myfun <- function(y) {
  if (is.character(y)) y <- as.integer(as.ordered(y))
  if (is.factor(y)) y <- as.integer(y)
  y
}
varToChange <- Map(myfun, varToChange)

UPDATE:Map永远不会修改变量,这在R中完成。使用Map返回的新值

f<- function(dt, x, y, k) {
  args <- Map(function(x) getColName(dt, x), list(x=x,y=y,k=k))

  ggplot(dt, aes_string(args$x,args$y, col=args$k)) + geom_jitter(alpha=0.1)
}
f(diamonds, 1,7,2)

答案 1 :(得分:1)

R中有两种迭代选择,迭代变量本身或索引。我通常建议迭代索引。这个案例说明了一个很大的优势,因为如果你使用索引,你的问题就不是问题了。

varToChange = list( 1:10, iris$Species[1:10], letters[1:10])
for (i in seq_along(varToChange)) {
  if (is.character(varToChange[[i]])) varToChange[[i]] <- as.integer(as.factor(varToChange[[i]]))
  if (is.factor(varToChange[[i]])) varToChange[[i]] <- as.integer(varToChange[[i]])
}

我还将as.ordered()替换为as.factor() - 有序因子和常规因子之间的唯一区别是建模中使用的默认对比。因为你只是强迫整数,所以并不重要。