How to specify the last column of a matrix - r

I have a matrix A, how can I represent the last column, since I want to sort the matrix based on that.

> A <- matrix(rnorm(16), 4, 4)
> ncol(A)
[1] 4
> # Get the last column
> A[,ncol(A)]
[1] 0.7593943 0.0726012 2.2784912 -0.2571095
> # If you want to sort based on the last column...
> A[order(A[,ncol(A)]),]
[,1] [,2] [,3] [,4]
[1,] -0.9013910 -0.06612518 -1.51267548 -0.2571095
[2,] 0.3851738 -0.81303780 0.01062751 0.0726012
[3,] -1.6940473 -1.15323294 -1.50261705 0.7593943
[4,] 0.3120409 -0.30047966 0.59672449 2.2784912

If A is your matrix then the last column of A is:
A[,ncol(A)]
If you are not familiar with bracket indexing in R, this code selects all rows of A (since the space before the comma is blank) and then the last column of A since R indexing begins at 1 (unlike languages like Python). ncol(A) returns the number of columns in A as an integer so indexing in this way gives your desired result.

Related

How to write an apply() function to limit each element in a matrix column to a maximum allowable value?

I'm trying to learn how to use the apply() functions.
Suppose we have a 3 row, 2 column matrix of test <- matrix(c(1,2,3,4,5,6), ncol = 2), and we would like the maximum value of each element in the first column (1, 2, 3) to not exceed 2 for example, so we end up with a matrix of (1,2,2,4,5,6).
How would one write an apply() function to do this?
Here's my latest attempt: test1 <- apply(test[,1], 2, function(x) {if(x > 2){return(x = 2)} else {return(x)}})
We may use pmin on the first column with value 2 as the second argument, so that it does elementwise checking with the recycled 2 and gets the minimum for each value from the first column
test[,1] <- pmin(test[,1], 2)
-output
> test
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 2 6
Note that apply needs the 'X' as an array/matrix or one with dimensions, when we subset only a single column/row, it drops the dimensions because drop = TRUE by default
If you really want to use the apply() function, I guess you're looking for something like this:
t(apply(test, 1, function(x) c(min(x[1], 2), x[2])))
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 2 6
But if you want my opinion, akrun's suggestion is definitely better.

R nrow function returning NULL or 1

This should be very simple but I cannot resolve it. I derive what I think is a matrix from the str_match_all function. It appears this is not the case, despite its appearance. I am able to extract the timestamp value from the first row of the 'matrix' by hard coding the indices in sapply [1,2]. I want to do the same thing for the last entry in the matrix and thought I would easily be able to extract the number of rows in the matrix to do this e.g. [nrow(sm),2], but cannot! See below:
sm <- str_match_all(regex_text, regex_list[row, "regex_pattern"] )
print(sm)
#This gives me this (which is good):
# [[1]]
# [,1] [,2] [,3]
# [1,] "09/08/2014 13:01CONTENT_ACCESS.preparing" "09/08/2014 13:01" "CONTENT_ACCESS.preparing"
# [2,] "09/08/2014 13:06CONTENT_ACCESS.preparing" "09/08/2014 13:06" "CONTENT_ACCESS.preparing"
# [3,] "09/08/2014 13:08CONTENT_ACCESS.preparing" "09/08/2014 13:08" "CONTENT_ACCESS.preparing"
#Get the first timestamp
start_t_stamp <- sapply(sm, function(x) x[1,2])
print(start_t_stamp)
# Also good, I get [1] "09/08/2014 13:01"
#Get the last timestamp. How do extract the 'number of rows' in sm?
#This returns NULL
print(nrow(sm))
#transform to matrix???
t_sm <- t(sm)
#This then prints "[1,] Character,9"
print(t_sm)
#Therfore this prints 1
print(nrow(t_sm))
Thanks in advance...

Can an R matrix contain different datatypes? Does this hacked-up matrix-of-lists work?

I read these:
https://stackoverflow.com/a/5159049/1175496
Matrices are for data of the same type.
https://stackoverflow.com/q/29732279/1175496
Vectors (and so matrix) can accept only one type of data
If matrix can only accept one data type, why can I do this:
> m_list<-matrix(list('1',2,3,4),2,2)
> m_list
[,1] [,2]
[1,] "1" 3
[2,] 2 4
The console output looks like I am combining character and integer data types.
The console output looks similar to this matrix:
> m_vector<-matrix(1:4,2,2)
> m_vector
[,1] [,2]
[1,] 1 3
[2,] 2 4
When I assign to m_list, it doesn't coerce the other values (as in https://stackoverflow.com/q/29732279/1175496 )
> m_list[2,2] <-'4'
> m_list
[,1] [,2]
[1,] "1" 3
[2,] 2 "4"
OK here is what I gather from replies so far:
Question
How can I have a matrix with different types?
Answer
You cannot; the elements are not different types; all (4) elements of this matrix are lists
all(
is.list(m_list[1,1]),
is.list(m_list[2,1]),
is.list(m_list[1,2]),
is.list(m_list[2,2]))
#[1] TRUE
Question
But I constructed matrix like this: matrix(list('1',2,3,4),2,2), how did this become a matrix of (4) lists, rather than a matrix of (4) characters, or even (4) integers?
Answer
I'm not sure. Even though the documentation says re: the first argument to matrix:
Non-atomic classed R objects are coerced by as.vector and all
attributes discarded.
It seems these are identical
identical(as.vector(list('1',2,3,4)), list('1',2,3,4))
#[1] TRUE
Question
But I assign a character ('4') to an element of m_list, how does that work?
m_list[2,2] <-'4'
Answer
It is "coerced", as if you did this:
m_list[2,2] <- as.list('4')
Question
If the elements in m_list are lists, is m_list equivalent to matrix(c(list('1'),list(2),list(3),list(4)),2,2)?
Answer
Yes, these are equivalent:
m_list <- matrix(list('1',2,3,4),2,2)
m_list2 <- matrix(c(list('1'),list(2),list(3),list(4)),2,2)
identical(m_list, m_list2)
#[1] TRUE
Question
So how can I retrieve the typeof the '1' hidden in m_list[1,1]?
Answer
At least two ways:
typeof(m_list[1,1][[1]])
#[1] "character"
...or, can directly do this (thanks, Frank) (since indexing has this "is applied in turn to the list, the selected component, the selected component of that component, and so on" behavior)...
typeof(m_list[[1,1]])
#[1] "character"
Question
How can I tell the difference between these two
m1 <- matrix(c(list(1), list(2), list(3), list(4)), 2, 2)
m2 <- matrix(1:4, 2, 2)
Answer
If you are using RStudio,
m1 is described as List of 4
m2 is described as int [1:2, 1:2] 1 2 3 4
..or else, just use typeof(), which for vectors and matrices, identifies the type of their elements... (thanks, Martin)
typeof(m1)
#[1] "list"
typeof(m2)
#[1] "integer"
class can also help distinguish, but you must wrap the matrices in vectors first:
#Without c(...)
class(m1)
#[1] "matrix"
class(m2)
#[1] "matrix"
#With c(...)
class(c(m1))
#[1] "list"
class(c(m2))
#[1] "integer"
...you could tell a subtle difference in the console output; notice how the m2 (containing integers) right-aligns its elements (because numerics are usually right-aligned)...
m1
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
m2
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
Short-Answer: Matrices in R cannot contain different data types. All data have to or will be transformed into either logical, numerical, character or list.
Matrices always contain the same type. If input data to matrix() have different data types, they will automatically transformed into the same type. Thus, all data will be either logical, numerical, character or list. And here is your case, in your example all elements are being transformed into individual lists.
> myList <- list('1',2,3,4)
> myMatrix <- matrix( myList ,2,2)
> myMatrix
[,1] [,2]
[1,] "1" 3
[2,] 2 4
> typeof(myMatrix)
"list"
If you want to transformed completely your data from a list, you need to unlist the data.
> myList <- list('1',2,3,4)
> myMatrix <- matrix( unlist(myList) ,2,2)
> myMatrix
[,1] [,2]
[1,] "1" "3"
[2,] "2" "4"
> typeof(myMatrix)
"character"
Picking up the comments, verify yourself:
typeof(m_list)
typeof(m_list[2,2])

subsetting matrix while preserving row.names

I'm trying to subset a matrix so that I only get the matrix where the first variable is larger than the second variable. I have the matrix out which is a 3000x2 matrix.
I tried
out<-out[out[,1] > out[,2]]
but this eliminates the row.names altogether, and I get a string of integers between 1 to 3000. Would there be a way to preserve the row.names?
Of note, if you only return a subset of one row to form a matrix with one dimension being unity, R will drop the row name:
m <- matrix(1:9, ncol = 3)
rownames(m) <- c("a", "b", "c")
m[1, ] # lost the row name
m[1, , drop = FALSE] # got row name back and a matrix
m[c(1,1), ] # the row name is back when result has nrow > 1
There appears to be no simple way of working around this other than checking for one-row result and assigning the row name.
A matrix is treated by R as a vector with columns and rows.
> A <- matrix(1:9, ncol=3)
# A is filled with 1,...,9 columnwise
> A
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
# only elements with even number in 2nd column of same row
> v <- A[A[,2] %% 2 == 0]
> m <- A[A[,2] %% 2 == 0,]
> v
[1] 1 3 4 6 7 9
> m
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 3 6 9
# The result of evaluating odd/even-ness of middle column.
# This boolean vector is repeated column-wise by default
# until all element's fate in A is determined.
> A[,2] %% 2 == 0
[1] TRUE FALSE TRUE
When you leave out the comma (v), then you address A as a 1-dimensional data structure and R implicitely handles your expression as a vector.
v is in that sense not "string of integers" but a vector of integers. When you add the comma, then you tell R that your condition only adresses the first dimension while indicating a second one (after the comma) - which causes R to handle your expression as a matrix (m).

Delete parts of a matrix that satisfy a condition in R

I would like to delete rows from a large matrix using the following criteria:
Any row that contains 100 in its second column should be removed.
How can this be done? I know how to select those rows but I'm not sure how to remove them using a rule.
R > mat = matrix(c(1,2,3,100,200,300), 3,2)
R > mat
[,1] [,2]
[1,] 1 100
[2,] 2 200
[3,] 3 300
R > (index = mat[,2] == 100)
[1] TRUE FALSE FALSE
R > mat[index, ]
[1] 1 100
R > mat[!index, ]
[,1] [,2]
[1,] 2 200
[2,] 3 300
Previously I was confused by the index with another method which, here is the solution by which:
R > (index2 = which(mat[,2] == 100))
[1] 1
R > mat[-index2, ]
[,1] [,2]
[1,] 2 200
[2,] 3 300
Watch out the different use for those index (! and -).
Here's how I would do it in Matlab with a matrix A.
Option 1
for (i=size(A,1):-1:0)
if (A(i,2)==100)
A(i,:)=[];
end
end
This loops over rows (starting at the bottom), and sets any row with 100 in the 2nd element to an empty set, which effectively deletes it.
Maybe you can convert this to r, or maybe it will help somebody else who is having this problem.
Option 2
logicalIndex=(A(:,2)==100);
A(logicalIndex,:)=[];
This first finds rows with 100 in the 2nd column, then deletes them all.

Resources