问题
I have a data frame called input
. The first column refers to an Article ID (ArtID
), the subsequent columns will be used to create the matrix.
Based on the ArtID
, I want R to generate a 2x2 matrix (more precise: It needs to be a numeric 2x2 matrix). Specifically, I want to create a matrix for the first row (ArtID == 1
), the second row(ArtID == 2
) and so on...
What I came up with so far is this:
for(i in 1:3) {stored.matrix = matrix(input[which(ArtID ==i),-1],nrow = 2)
This gives me a 2x2 matrix, but it is not numeric (which it needs to be).
If I apply as.numeric
, the matrix is no longer a 2x2 matrix.
How do I get a 2x2 numerical matrix?
Minimal reproducible example:
ArtID = c(1,2,3)
AC_AC = c(1,1,1)
MKT_AC = c(0.5,0.6,0.2)
AC_MKT = c(0.5,0.6,0.2)
MKT_MKT = c(1,1,1)
input = data.frame(ArtID, AC_AC, MKT_AC, AC_MKT, MKT_MKT)
stored.matrix = matrix(input[which(ArtID ==i),-1],nrow = 2)
# [,1] [,2]
#[1,] 1 0.5
#[2,] 0.5 1
is.numeric(stored.matrix)
# [1] FALSE
as.numeric(stored.matrix)
## [1] 1.0 0.5 0.5 1.0
As you can see after applying as.numeric()
the matrix is no longer 2x2.
Can anyone help?
回答1:
when you have only numerical values in your data frame, it is more appropriate to use a matrix. Convert your data frame to a matrix will solve all problem. Also,
input <- data.matrix(input)
ArtID = c(1,2,3)
AC_AC = c(1,1,1)
MKT_AC = c(0.5,0.6,0.2)
AC_MKT = c(0.5,0.6,0.2)
MKT_MKT = c(1,1,1)
input = data.frame(ArtID, AC_AC, MKT_AC, AC_MKT, MKT_MKT)
input <- data.matrix(input) ## <- this line
stored.matrix = matrix(input[which(ArtID ==i),-1], 2)
is.numeric(stored.matrix)
# [1] TRUE
So what was the problem?
If input
is a data frame, input[which(ArtID == i),-1]
by row subsetting still returns a data frame. A data frame is a special type of list. When you feed a list to matrix()
, you get into a situation of matrix list.
If you read ?matrix
for what data it can take, you will see:
data: an optional data vector (including a list or ‘expression’
vector). Non-atomic classed R objects are coerced by
‘as.vector’ and all attributes discarded.
Note that a list is also of vector data type (e.g., is.vector(list(a = 1))
gives TRUE
), so it is legitimate to feed a list to matrix
. You can try
test <- matrix(list(a = 1, b = 2, c = 3, d = 4), 2)
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
This is indeed a matrix in the sense that class(test)
give "matrix"), but
str(test)
#List of 4
# $ : num 1
# $ : num 2
# $ : num 3
# $ : num 4
# - attr(*, "dim")= int [1:2] 2 2
typeof(test)
# [1] "list"
so it is not the usual numerical matrix we refer to.
The input list can be ragged, too.
test <- matrix(list(a = 1, b = 2:3, c = 4:6, d = 7:10), 2)
# [,1] [,2]
#[1,] 1 Integer,3
#[2,] Integer,2 Integer,4
str(test)
#List of 4
# $ : num 1
# $ : int [1:2] 2 3
# $ : int [1:3] 4 5 6
# $ : int [1:4] 7 8 9 10
# - attr(*, "dim")= int [1:2] 2 2
And I was wondering why
typeof()
gives me list... :)
Yes, so had realized something unusual. The storage mode of a matrix is determined by that of its element. For a matrix list, elements are list, hence the matrix has "list" mode.
回答2:
You could use unlist()
:
matrix(unlist(input[ArtID ==i,-1]),2)
or use
storage.mode(m) <- "numeric"
来源:https://stackoverflow.com/questions/39041037/why-is-this-matrix-not-numeric-then-as-numeric-destroys-the-matrix-and-return