0
$\begingroup$

I have a list where each element is a matrix, and I want to order each matrix individually

Order a matrix is as easy as this:

data <- data[order(data$value),]

But I am struggling to order a list of matrix individually

I have tried this with some variations:

 for(i in 1:lenght(data)){
 data[i] <- data[i][order(data[i]$value),]
 }

data is the list that contains matrices

I have also tried with apply functions

Some ideas?

Thanks!!

All the code:

#The aim is to show one hospital for each state given an outcome 
#in the posotion num of the ranking, its a learning exercise

rankall <- function(outcome, num = "best"){

if (outcome == "heart attack"){
  col <- 11
}else if(outcome == "heart failure"){
  col <- 17
}else if(outcome == "pneumonia"){
  col <- 23
}else{
  stop("invalid outcome")
}

data <- read.csv("outcome-of-care-measures.csv", colClasses = "character")

data <- data[, c(2, 7,col)]

colnames(data) <- c("Hospital", "State", "value")
data$value <- as.numeric(data$value)
data <- data[complete.cases(data),]
data <- split(data, data$State)

#data2 is the final result dataframe
data2 <- data.frame(matrix(nrow = 0, ncol = 3))
colnames(data2) <- c("Hospital", "State", "value")

#From here is what I do not know how to do it.

#data is a list of matrices, each matrix corresponds to a state
#data2 is the result dataframe, where I am going to add the row num of each 
matrix in data

#1. Order each matrix in data by value and alfabetically if tie
#2. Add to data 2 the row num of each matrix in data once they are sort

for(i in 1:lenght(data)){

data[i] <- data[i][order(data[i]$Hospital),]
data[i] <- data[i][order(data[i]$value),]

if(num =="best"){
  num = 1;
}else if(num == "worst"){
  num = nrow(data[i])
}

num <- as.numeric(num)

rbind(data2,data[i][num])

}

return(data2)

}

Sorry about identations, it changed when I paste the code

$\endgroup$
4
  • $\begingroup$ What is the output of your code? An error or incorrect results? - perhaps try breaking it down further by adding the sorted matrices into a new list, instead of overwriting the matrix you just sorted. $\endgroup$
    – n1k31t4
    Commented Jul 22, 2018 at 11:02
  • $\begingroup$ The code that I post it is only for know what I want to do. Because lenght(data) give me an error saying that could not find a function"lenght" and if I change that to 1:4 only for test purposes it gives me an error saying in the function order the argument is not a vector but when I do it with an unquie matrix its work perfect. The problem is that I think I do not know how to work with a list of matrices $\endgroup$ Commented Jul 22, 2018 at 11:10
  • $\begingroup$ But what is the problem? What have you actually tried? If we know the concrete problem/error, a better answer can be given. Given what you say and your code examples, I don't know what the problem is, because it looks like it would work. $\endgroup$
    – n1k31t4
    Commented Jul 22, 2018 at 11:18
  • $\begingroup$ There you have the code. I think my approach to this kind of problem is bad and I do not know how to reference and treat matrices inside a list. $\endgroup$ Commented Jul 22, 2018 at 11:45

2 Answers 2

0
$\begingroup$

Because I did not have your exact data (I don't have the csv file), I created a dummy dataframe (swiped from this tutorial):

numPeople = 10
sex=sample(c("male","female"),numPeople,replace=T)
age = sample(14:102, numPeople, replace=T)
income = sample(20:150, numPeople, replace=T)
minor = age<18

population = data.frame(sex=sex, age=age, income=income, minor=minor)
population

> population
      sex age income minor
1    male  34    130 FALSE
2    male  48     86 FALSE
3  female 101     36 FALSE
4    male  64     78 FALSE
5  female  97     92 FALSE
6    male  19     45 FALSE
7  female  42    124 FALSE
8  female  24     68 FALSE
9  female  24     96 FALSE
10 female  91     30 FALSE

This means you will have to adjust the variable names and so on to match your example, but can learn how to order a list of matrices. More specifically, you really have a list of data.frame objects, after using the split function. it is important to notice the difference between a data.frame and a matrix, as they can behave differently.

I will split the data.frame by the sex column:

l = split(population, population$sex)

You can test that each element of the resulting list is indeed a data.frame (and not a matrix) by running:

> is.data.frame(l[[1]])
[1] TRUE

Notice that you have to use the doublesquare brackets to access the actual element of the list. Single square brackets will return something else:

> is.data.frame(l[1])
[1] FALSE

Tt is a named list-element and needs to be referenced by using (in my case) one of the names of the group that we split on: male or female Below I comment the code heavily to explain what each step does.

> l[1]
$female                          # this is the name of the list element
     sex age income minor
1 female  20     42 FALSE
6 female  75    103 FALSE
7 female  30    148 FALSE

So we can access the actual element two ways:

  1. by name:

    > l[1]$female
         sex age income minor
    1 female  20     42 FALSE
    6 female  75    103 FALSE
    7 female  30    148 FALSE
    
  2. by double square brackets:

    > l[[1]]
     sex age income minor
    1 female  20     42 FALSE
    6 female  75    103 FALSE
    7 female  30    148 FALSE
    

That all being said, he is a working example of sorting a list (vector, holding lists) containing data.frames:

l = split(population, population$sex)    # population is defined as shown above
N = length(l)

results <- vector("list", N)

for(i in 1:N) {

    results[[i]] <- l[[i]][order(l[[i]]$age),]
}

I specify the length of the vector when I create it, as we know how long the resulting list will be in advance. ... and check the results:

> results[[1]]
    sex age income minor
8 female  66     90 FALSE
5 female  69    131 FALSE
2 female  70     52 FALSE
9 female  95     43 FALSE

> results[[2]]
    sex age income minor
6  male  18     87 FALSE
4  male  61     97 FALSE
3  male  64    131 FALSE
7  male  72     93 FALSE
1  male  82    107 FALSE
10 male  92     42 FALSE

The results depend on random choice when creating population at the beginning, using sample().

$\endgroup$
1
  • $\begingroup$ Sorry, for the next time i will include all the data. The main problem was that i had to use double brackets instead of one. THANKS!!! $\endgroup$ Commented Jul 22, 2018 at 14:18
0
$\begingroup$

Final code(this works OK):

rankall <- function(outcome, num = "best"){

if (outcome == "heart attack"){
  col <- 11
}else if(outcome == "heart failure"){
  col <- 17
}else if(outcome == "pneumonia"){
  col <- 23
}else{
  stop("invalid outcome")
}

data <- read.csv("outcome-of-care-measures.csv", colClasses = "character")

data <- data[, c(2, 7,col)]

colnames(data) <- c("Hospital", "State", "value")
data$value <- as.numeric(data$value)
data <- data[complete.cases(data),]
data <- split(data, data$State)


N <- length(data)
data2 <- vector("list", N)
for(i in 1:N){

  data[[i]] <- data[[i]][order(data[[i]]$value, data[[i]]$Hospital),]

  if(num =="best"){
    t <- 1;
  }else if(num == "worst"){
    t <- nrow(data[[i]])
  }else{
    t <- num
  }

  data2[[i]] <- data[[i]][t,]

}

return(data2)

}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.