why does the following code cause an error?
attach(mtcars)
df <- mtcars[,c(1:4,"qsec")]
# Error in `[.data.frame`(mtcars, , c(1:4, "qsec")) :
# undefined columns selected
While
df <- mtcars[,c(1:4)]
and
df <- mtcars[,"qsec"]
work okay? (Although the "qsec" column name is lost).
This one does not work either:
mtcars <- mtcars
df <- mtcars[,c(1:4,mtcars$qsec)]
CodePudding user response:
If you look at ?Extract
(or ?"["
) you'll get the R help for the bracket []
notation, which can use either numbers to specify position, or character values to match the names of the object (column names, in the case of data frames).
i, j, ... indices specifying elements to extract or replace. Indices are numeric or character vectors or empty (missing) or NULL. Numeric values are coerced to integer as by as.integer (and hence truncated towards zero). Character vectors will be matched to the names of the object (or for matrices/arrays, the dimnames): see ‘Character indices’ below for further details.
If you want to specify by both name & position you need to create a vector that is all strings or all numbers. All the elements in an R vector need to be the same data type. As @zheyuan-li had noted, R will implicitly convert your vector c(1:4, "qsec")
to be "1" "2" "3" "4" "qsec"
, and there are no columns named "1", "2", "3", or "4".
You could use the syntax below to convert the position names to strings so they can be the same type as the "qsec"
specification.
mtcars[, c(names(mtcars)[1:4], "qsec")]
# where the c() part = "mpg" "cyl" "disp" "hp" "qsec"
or going the other way, you could convert the name qsec
to a number (7
) that harmonizes with 1:4
:
mtcars[, c(1:4, grep("qsec", colnames(mtcars)))]
# where the c() part = 1 2 3 4 7