Jorge Sanmarcos
Jorge Sanmarcos

Reputation: 101

How can I get row names from the apply() function's output?

I'm learning R and have a tibble with some World Bank data. I used the apply() function in a slice of the columns and applied the standard deviation over the values, in this way: result <- apply(df[6:46],2,sd,na.rm=TRUE).

The result is an object with two columns with no header, one column is all the names of the tibble columns that were selected and the other one is the standard deviation for each column. When I use the typeof() command in the output, the result is 'double'. The R documentation says the output of apply() is a vector, an array or a list.

I need to know this because I want to extract all the row names and using the command rownames(result) throws the output NULL. What can I do to extract the row names of this object?

enter image description here

Tried rownames(result) and row.names(result and none worked.

Upvotes: 3

Views: 2508

Answers (2)

akrun
akrun

Reputation: 887223

Here, the sd returns a single value and as the apply is with MARGIN = 2 i,e columnwise, we are getting a named vector. So, names(out) would get the names instead of row.names. Using a reproducible example with the inbuilt dataset iris

data(iris)
out <- apply(iris[1:4], 2, sd, na.rm = TRUE)
names(out)
#[1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width" 

Also, by wrapping the output of apply with data.frame, we can use the row.names

out1 <- data.frame(val = out)
row.names(out1)
#[1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width" 

If we need a data.frame as output, this can he directly created with data.frame call

data.frame(names = names(out), values = out)

Also, this can be done in tidyverse

library(dplyr)
library(tidyr)
iris %>%
     summarise_if(is.numeric, sd, na.rm = TRUE) %>%
     gather
#     key     value
#1 Sepal.Length 0.8280661
#2  Sepal.Width 0.4358663
#3 Petal.Length 1.7652982
#4  Petal.Width 0.7622377

Or convert to a list and enframe

library(tibble)
iris %>%
    summarise_if(is.numeric, sd, na.rm = TRUE) %>%
    as.list %>% 
    enframe

Upvotes: 2

Ronak Shah
Ronak Shah

Reputation: 389047

We can use stack to convert the vector output into dataframe.

temp <- stack(apply(df[6:46],2,sd,na.rm=TRUE))

Now, we can access all the column names with temp$ind and values of sd in temp$values.

Using mtcars as example,

temp <- stack(apply(mtcars, 2, sd, na.rm = TRUE))
temp

#      values  ind
#1    6.02695  mpg
#2    1.78592  cyl
#3  123.93869 disp
#4   68.56287   hp
#5    0.53468 drat
#6    0.97846   wt
#7    1.78694 qsec
#8    0.50402   vs
#9    0.49899   am
#10   0.73780 gear
#11   1.61520 carb

We can also use this with sapply and lapply

stack(sapply(mtcars,sd, na.rm = TRUE))
#and
stack(lapply(mtcars,sd, na.rm = TRUE))

Upvotes: 3

Related Questions