循环遍历 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] <- NULL
失败,而 Adata[,SpecialNames] <- NA
工作 - 它是一种安全功能,因为分配 NULL
会更改 data.frame
的结构。要击败它,您需要mydf[[specialnames[1]]] <- NULL
,注意使用[[
。 Hadley 的 note 对此帮助了我。
【参考方案1】:
您的循环非常接近 - 您缺少 [
和 [[
的用法和含义中的一个微妙特征。有关详细信息,请参阅 Hadley Wickham 关于子集的this 注释。
要获得您想要的性能(分配NULL
以删除一列),您必须使用[[
。使用mydf[, specialnames] <- NULL
会抛出错误。
我同意这有点令人困惑,因为mydf[, specialnames] <- 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] <- NULL
会抛出一个错误——因为这就是引发 OP 问题的原因。在需要删除列的情况下,上述方法不会起作用。以上是关于循环遍历 R 中列名的特定子集的主要内容,如果未能解决你的问题,请参考以下文章
如何避免循环遍历 pandas 中的分类变量以查看/操作数据帧切片/子集