考虑以下模拟片段:
k <- 1:5
x <- seq(0,10,length.out = 100)
dsts <- lapply(1:length(k), function(i) cbind(x=x, distri=dchisq(x,k[i]),i) )
dsts <- do.call(rbind,dsts)
为什么这段代码会抛出错误(dsts是矩阵):
subset(dsts,i==1)
#Error in subset.matrix(dsts, i == 1) : object 'i' not found
即便如此:
colnames(dsts)[3] <- 'iii'
subset(dsts,iii==1)
但不是这个(矩阵被强制为数据帧):
subset(as.data.frame(dsts),i==1)
这个可以在已定义x
的地方工作:
subset(dsts,x> 500)
此行的subset.matrix()
发生错误:
else if (!is.logical(subset))
这是一个应该报告给R Core的错误吗?
答案 0 :(得分:4)
您所描述的行为是按设计进行的,并记录在?subset
帮助页面上。
从帮助页面:
对于数据框,子参数适用于行。请注意,子集将在数据框中进行评估,因此可以将列引用(通过名称)作为表达式中的变量(请参阅示例)。
在R中,data.frames和matrices是非常不同类型的对象。如果这导致问题,则可能是您的数据使用了错误的数据结构。如果使用矩阵运算,矩阵实际上是必需的。如果您将列视为行观察的不同属性,那么您应该首先将数据存储在data.frame中。您可以将所有值存储在一个简单的向量中,其中每三个值代表一个观察值,但这也是数据数据结构的不良选择。我不确定你是否试图通过选择矩阵来提高效率,但这似乎是错误的选择。
data.frame存储为命名列表,而矩阵存储为尺寸矢量。列表可以用作一个环境,可以轻松评估该上下文中的变量名称。两者之间最大的区别是data.frames可以包含不同类的列(数字,字符,日期),而矩阵只能保存一个data.type的值。在不丢失信息的情况下,您无法轻松地在两者之间进行转换。
认为$
仅适用于data.frames。
dd <- data.frame(x=1:10)
dd$x
mm <- matrix(1:10, ncol=1, dimnames=list(NULL, "x"))
mm$x # Error
如果要对矩阵进行子集化,最好使用标准[
子集而不是子设置函数。
dsts[ dsts[,"i"]==1, ]
很长一段时间以来,这种行为一直是R的一部分。对此行为的任何更改都可能会对依赖于在特定上下文中评估的变量的现有代码引入重大更改。我认为问题在于谁首先告诉你使用矩阵。您应该使用cbind()
data.frame()