为什么[ - 对名称不可能对列进行子集化(即删除)?

a d*_*ben 17 r subset dataframe

我非常担心这会被提出并且会被低估,但是我没有在文档中找到答案(?"["),并且发现它很难搜索.

data(wines)
# This is allowed:
alcoholic <- wines[, 1]
alcoholic <- wines[, "alcohol"]
nonalcoholic <- wines[, -1]
# But this is not:
fail <- wines[, -"alcohol"]
Run Code Online (Sandbox Code Playgroud)

我知道有两种解决方案,但对它们的需求感到沮丧.

win <- wines[, !colnames(wines) %in% "alcohol"]  # snappy
win <- wines[, -which(colnames(wines) %in% "alcohol")]  # snappier!
Run Code Online (Sandbox Code Playgroud)

flo*_*del 18

当你这样做

wines[, -1]
Run Code Online (Sandbox Code Playgroud)

-1在被使用之前进行评估[.如您所知,-一元运算符不适用于类的对象character,因此使用"alcohol"执行相同操作将导致您:

Error in -"alcohol" : invalid argument to unary operator
Run Code Online (Sandbox Code Playgroud)

您可以在备选方案中添加以下内容:

wines[, -match("alcohol", colnames(wines))]
wines[, setdiff(colnames(wines), "alcohol")]
Run Code Online (Sandbox Code Playgroud)

但你应该知道负面索引的风险,例如,看看如果你错误地输入"alcool"会发生什么(原文如此)所以你的第一个建议和最后一个建议(@Ananda's)应该是首选.如果您提供的名称不属于您的数据,您可能还需要编写一个会出错的函数.


Ben*_*ker 8

另一种可能性

subset(wines,select=-alcohol)
Run Code Online (Sandbox Code Playgroud)

你甚至可以这样做

subset(wines,select=-c(alcohol,other_drop))
Run Code Online (Sandbox Code Playgroud)

实际上,如果你想要删除一组连续的列,你甚至可以

subset(wines,select=-(first_drop:last_drop))
Run Code Online (Sandbox Code Playgroud)

这可能很方便(尽管IMO危险地依赖于列的顺序,这可能是脆弱的:grep如果有某种方法来识别列,或者列组的更明确的单独定义,我可能更喜欢基于解决方案) .

在这种情况下subset使用非标准评估,如在别处讨论的那样在某些情况下可能是危险的.但由于其可读性,我仍然喜欢简单的顶级数据操作.


42-*_*42- 6

另一种使用数字索引的方法,并推广到你想要删除一堆类似命名列的情况:

dfrm[ , -grep("^val", names(dfrm) )] #remove columns starting with "val"
Run Code Online (Sandbox Code Playgroud)

(我把我的投票给了flodel,因为他的答案描述了"为什么"一个"减号"不起作用.基本上是因为R作者没有为此目的重载" - "运算符.他们也没有超载" +"以某些语言的方式进行连接.