Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does sapply return a matrix that I need to transpose, and then the transposed matrix will not attach to a dataframe?

I would appreciate insight into why this happens and how I might do this more eloquently.

When I use sapply, I would like it to return a 3x2 matrix, but it returns a 2x3 matrix. Why is this? And why is it difficult to attach this to another data frame?

a <- data.frame(id=c('a','b','c'), var1 = c(1,2,3), var2 = c(3,2,1))
out <- sapply(a$id, function(x) out = a[x, c('var1', 'var2')])
#out is 3x2, but I would like it to be 2x3
#I then want to append t(out) (out as a 2x3 matrix) to b, a 1x3 dataframe
b <- data.frame(var3=c(0,0,0))

when I try to attach these,

b[,c('col2','col3')] <- t(out)

The error that I get is:

Warning message:
In `[<-.data.frame`(`*tmp*`, , c("col2", "col3"), value = list(1,  :
  provided 6 variables to replace 2 variables

although the following appears to give the desired result:

rownames(out) <- c('col1', 'col2')
b <- cbind(b, t(out))

I can not operate on the variables:

b$var1/b$var2

returns

Error in b$var1/b$var2 : non-numeric argument to binary operator

Thanks!

like image 447
David LeBauer Avatar asked Nov 10 '10 01:11

David LeBauer


People also ask

Why is Sapply returning a list?

The real reason for this is that sapply doesn't know what your function will return without calling it. In your case the function returns a logical , but since sapply is given an empty list, the function is never called. Therefore, it has to come up with a type and it defaults to list .

How do I transpose a Dataframe in R?

To interchange rows with columns, you can use the t() function. For example, if you have the matrix (or dataframe) mat you can transpose it by typing t(mat) . This will, as previously hinted, result in a new matrix that is obtained by exchanging the rows and columns.

How do you transpose a matrix in R?

Rotating or transposing R objects You can rotate the data. frame so that the rows become the columns and the columns become the rows. That is, you transpose the rows and columns. You simply use the t() command.

How do I transpose columns and rows in R?

Thus, to convert columns of an R data frame into rows we can use transpose function t. For example, if we have a data frame df with five columns and five rows then we can convert the columns of the df into rows by using as. data. frame(t(df)).


1 Answers

To expand on DWin's answer: it would help to look at the structure of your out object. It explains why b$var1/b$var2 doesn't do what you expect.

> out <- sapply(a$id, function(x) out = a[x, c('var1', 'var2')])
> str(out)  # this isn't a data.frame or a matrix...
List of 6
 $ : num 1
 $ : num 3
 $ : num 2
 $ : num 2
 $ : num 3
 $ : num 1
 - attr(*, "dim")= int [1:2] 2 3
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:2] "var1" "var2"
  ..$ : NULL

The apply family of functions are designed to work on vectors and arrays, so you need to take care when using them with data.frames (which are usually lists of vectors). You can use the fact that data.frames are lists to your advantage with lapply.

> out <- lapply(a$id, function(x) a[x, c('var1', 'var2')])  # list of data.frames
> out <- do.call(rbind, out) # data.frame
> b <- cbind(b,out)
> str(b)
'data.frame':   3 obs. of  4 variables:
 $ var3: num  0 0 0
 $ var1: num  1 2 3
 $ var2: num  3 2 1
 $ var3: num  0 0 0
> b$var1/b$var2
[1] 0.3333333 1.0000000 3.0000000
like image 144
Joshua Ulrich Avatar answered Nov 03 '22 06:11

Joshua Ulrich