循环遍历 R 中列名的特定子集

Posted

技术标签:

【中文标题】循环遍历 R 中列名的特定子集【英文标题】:Looping over a specific subset of column names in R 【发布时间】:2013-11-19 08:09:36 【问题描述】:

我有一个数据框 AData,我提取了它的列名的某个子集,比如 SpecialNames。我想知道如何在 for 循环中引用这些列。

我当前的代码如下所示:

SpecialNames <- setdiff(colnames(AData), colnames(BData))

for ( i in SpecialNames ) 

    AData$i <- NULL # Do something to AData$i such as delete it or something else


唉,AData$i 似乎没有引用名为 i 的数据框 AData 的列。有什么不同的语法可以给我吗?

我在这篇文章here 中读到:“$ 用于交互使用。相反,在编程时,即要解释列名时,您需要使用 [ 或 [[,因此我替换了 sample$ i.imp with sample[[paste0(i, '.impt')]]".

根据这个评论,我猜想我一直在寻找的语法可能是 AData$[i] 或 AData$[[i]] 或 AData$[[paste0(i)]] 但这些似乎都不是也可以工作。

有什么想法吗?

【问题讨论】:

你能提供一些样本数据和你想要的结果吗?尝试阅读this。 您在R 中遇到了我认为的设计缺陷。 Adata[,SpecialNames] &lt;- NULL 失败,而 Adata[,SpecialNames] &lt;- NA 工作 - 它是一种安全功能,因为分配 NULL 会更改 data.frame 的结构。要击败它,您需要mydf[[specialnames[1]]] &lt;- NULL,注意使用[[。 Hadley 的 note 对此帮助了我。 【参考方案1】:

您的循环非常接近 - 您缺少 [[[ 的用法和含义中的一个微妙特征。有关详细信息,请参阅 Hadley Wickham 关于子集的this 注释。

要获得您想要的性能(分配NULL 以删除一列),您必须使用[[。使用mydf[, specialnames] &lt;- NULL 会抛出错误。

我同意这有点令人困惑,因为mydf[, specialnames] &lt;- NA 会起作用:我认为这是关于前者改变data.frame 的结构而后者这样做......

这样你的函数就变成了:

for (name in specialnames)  
   mydf[[name]] <- NULL

所以设置我们有:

set.seed(1)
mydf <- data.frame(A = c(1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4),
               B = LETTERS[c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2)],
               matrix(sample(100, 36, replace = TRUE), nrow = 12))

## Here is your vector of special names
specialnames <- setdiff(names(mydf), c("A", "B"))

在循环之后我们会得到:

R> mydf
   A B
1  1 A
2  1 A
3  1 A
4  2 A
5  2 A
6  3 B
7  3 B
8  3 B
9  3 B
10 4 B
11 4 B
12 4 B

【讨论】:

【参考方案2】:

不知道自己在做什么,很难说for 循环是否可行;不过,希望这能帮助您顺利上路:

## Sample data is always nice
set.seed(1)
mydf <- data.frame(A = c(1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4),
                   B = LETTERS[c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2)],
                   matrix(sample(100, 36, replace = TRUE), nrow = 12))

## Here is your vector of special names
specialnames <- setdiff(names(mydf), c("A", "B"))

## Here is a `for` loop that will print the first two rows
##   of each column named in "specialnames"
## THIS IS NOT HOW I WOULD NORMALLY DO THIS IN R
## -------------------------------------------------------
for (i in seq_along(specialnames)) 
  print(head(mydf[specialnames[i]], 2))


注意事项(也许):

for (i in seq_along(specialnames))seq_along(或i in 1:length(specialnames) 或类似的东西)很重要。 您似乎误解了[[[ 的用法。尝试以下方法来了解他们的工作: mydf["A"] mydf[["A"]] mydf[1, c("A", "B")] 看here和here的两个问题。

【讨论】:

【参考方案3】:

您不需要for 循环,您可以直接访问列。这是一个例子:

Adata <- data.frame(a=rnorm(5), b=rnorm(5), c=rnorm(5))
SpecialNames <- c("b", "c")
Adata[,SpecialNames] <- NA

给你:

            a  b  c
1 -0.95619055 NA NA
2 -0.20250939 NA NA
3 -1.06609997 NA NA
4  0.06337307 NA NA
5  0.77234892 NA NA

您确定要使用NULL 吗? NA 通常用于缺失值,见here。

【讨论】:

值得注意的是,Adata[,SpecialNames] &lt;- NULL 会抛出一个错误——因为这就是引发 OP 问题的原因。在需要删除列的情况下,上述方法不会起作用。

以上是关于循环遍历 R 中列名的特定子集的主要内容,如果未能解决你的问题,请参考以下文章

T-SQL for 循环遍历列名并插入

循环遍历 pandas 列名以创建列表

如何避免循环遍历 pandas 中的分类变量以查看/操作数据帧切片/子集

如何遍历表的列名并将值传递给 MSSQL while 循环中的 UDF

在 R 函数中为子集插入列名时遇到问题

Oracle过程 - 选择所有表,然后循环遍历这些表的记录