对于初学者:我现在在这个问题上搜索了几个小时 - 所以如果答案应该是微不足道的,请原谅我......
我想要做的是从data.frame中删除一行(编号101)。它包含测试数据,不应出现在我的分析中。我的问题是:每当我从data.frame中进行子集化时,属性(特别是注释)都会丢失。
str(x)
# x has comments for each variable
x <- x[1:100,]
str(x)
# now x has lost all comments
有充分证据表明,子集将丢弃所有属性 - 到目前为止,它非常清楚。手册(例如http://stat.ethz.ch/R-manual/R-devel/library/base/html/Extract.data.frame.html)甚至建议了一种保留属性的方法:
## keeping special attributes: use a class with a
## "as.data.frame" and "[" method:
as.data.frame.avector <- as.data.frame.vector
`[.avector` <- function(x,i,...) {
r <- NextMethod("[")
mostattributes(r) <- attributes(x)
r
}
d <- data.frame(i= 0:7, f= gl(2,4),
u= structure(11:18, unit = "kg", class="avector"))
str(d[2:4, -1]) # 'u' keeps its "unit"
到目前为止,我还不知道究竟发生了什么。但是,只需运行这些行(除了最后三行)不会改变我的子集的行为。使用带有适当向量的命令subset()(100次TRUE + 1 FALSE)给出了相同的结果。简单地将属性存储到变量并在子集之后恢复它也不起作用。
# Does not work...
tmp <- attributes(x)
x <- x[1:100,]
attributes(x) <- tmp
当然,我可以将所有注释写入向量(var =&gt; comment),子集并使用循环将其写回 - 但这似乎不是一个有根据的解决方案。而且我很确定在将来的分析中我会遇到其他相关属性的数据集。
所以这就是我在stackoverflow,Google和脑力方面的努力陷入困境的地方。如果有人能帮我提示,我将非常感激。谢谢!
答案 0 :(得分:10)
如果我理解正确,您在data.frame中有一些数据,而data.frame的列具有与之关联的注释。或许像以下那样?
set.seed(1)
mydf<-data.frame(aa=rpois(100,4),bb=sample(LETTERS[1:5],
100,replace=TRUE))
comment(mydf$aa)<-"Don't drop me!"
comment(mydf$bb)<-"Me either!"
所以这会给你类似
的东西> str(mydf)
'data.frame': 100 obs. of 2 variables:
$ aa: atomic 3 3 4 7 2 7 7 5 5 1 ...
..- attr(*, "comment")= chr "Don't drop me!"
$ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2 2 5 4 2 1 3 5 3 ...
..- attr(*, "comment")= chr "Me either!"
当您对此进行子集化时,评论将被删除:
> str(mydf[1:2,]) # comment dropped.
'data.frame': 2 obs. of 2 variables:
$ aa: num 3 3
$ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2
要保留注释,请按照上面的说明(从文档中)定义函数[.avector
,然后将相应的类属性添加到data.frame中的每个列(编辑:保持bb
的因子水平,将"factor"
添加到bb
的类中。):
mydf$aa<-structure(mydf$aa, class="avector")
mydf$bb<-structure(mydf$bb, class=c("avector","factor"))
以便保留评论:
> str(mydf[1:2,])
'data.frame': 2 obs. of 2 variables:
$ aa:Class 'avector' atomic [1:2] 3 3
.. ..- attr(*, "comment")= chr "Don't drop me!"
$ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2
..- attr(*, "comment")= chr "Me either!"
修改强>
如果您的data.frame中有许多列要保留您的属性,则可以使用lapply
( EDITED 来包含原始列类):
mydf2 <- data.frame( lapply( mydf, function(x) {
structure( x, class = c("avector", class(x) ) )
} ) )
但是,这会删除与data.frame本身相关的注释(例如comment(mydf)<-"I'm a data.frame"
),所以如果你有,请将它们分配给新的data.frame:
comment(mydf2)<-comment(mydf)
然后你有
> str(mydf2[1:2,])
'data.frame': 2 obs. of 2 variables:
$ aa:Classes 'avector', 'numeric' atomic [1:2] 3 3
.. ..- attr(*, "comment")= chr "Don't drop me!"
$ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2
..- attr(*, "comment")= chr "Me either!"
- attr(*, "comment")= chr "I'm a data.frame"
答案 1 :(得分:4)
对于那些根据BenBarnes解释寻找“全押”解决方案的人:就是这样。
(如果这对你有用,请将你的“向上”发给BenBarnes的帖子)
# Define the avector-subselection method (from the manual)
as.data.frame.avector <- as.data.frame.vector
`[.avector` <- function(x,i,...) {
r <- NextMethod("[")
mostattributes(r) <- attributes(x)
r
}
# Assign each column in the data.frame the (additional) class avector
# Note that this will "lose" the data.frame's attributes, therefore write to a copy
df2 <- data.frame(
lapply(df, function(x) {
structure( x, class = c("avector", class(x) ) )
} )
)
# Finally copy the attribute for the original data.frame if necessary
mostattributes(df2) <- attributes(df)
# Now subselects work without losing attributes :)
df2 <- df2[1:100,]
str(df2)
好事:当将类附加到所有data.frame的元素时,子选择永远不会再打扰属性。
好的 - 有时候我很惊讶在R中进行最简单的操作是多么复杂。但是如果我只是在SPSS中标记并删除了这个案例,我肯定没有学过“类”功能;)
答案 2 :(得分:1)
这是由sticky
包解决的。 (完全披露:我是包的作者。)将sticky()
应用于向量,并通过子集操作保留属性。例如:
> df <- data.frame(
+ sticky = sticky( structure(1:5, comment="sticky attribute") ),
+ nonstick = structure( letters[1:5], comment="non-sticky attribute" )
+ )
>
> comment(df[1:3, "nonstick"])
NULL
> comment(df[1:3, "sticky"])
[1] "sticky attribute"
这适用于任何属性,而不仅仅是comment
。
有关详细信息,请参阅sticky
包:
答案 3 :(得分:0)
我花了好几个小时试图弄清楚如何在对数据帧进行子集化(删除列)时保留属性数据(特别是变量标签)。答案很简单,我简直不敢相信。只需使用Hmisc包中的函数spss.get,然后无论您如何子集,都会保留变量标签。