13

As an intermediate step I generate a data frame with one column as character strings and the rest are numbers. I'd like to convert it to a matrix, but first I have to convert that character column into row names and remove it from the data frame.

Is there a simpe way to do this in dplyr? A function like to_rownames() that is opposite to add_rownames()?

I saw a solution using a custom function, but it's really out of dplyr philosophy.

zx8754
  • 52,746
  • 12
  • 114
  • 209
yuk
  • 19,098
  • 13
  • 68
  • 99
  • I don't think the dplyr philosophy is meant to encompass non-data.frames. Its current tagline is "plyr specialized for data frames" https://github.com/hadley/dplyr – Frank Apr 18 '16 at 21:15
  • @Frank, The function is not necessary to be used to convert data frame to matrix. What if I just need to change row names based on existing field? Or using row names out of dplyr philosophy at all? – yuk Apr 18 '16 at 21:20
  • 2
    Hm, I don't know. My insight into the package doesn't go much beyond the tagline :) You can see hadley speaking against rownames here, though: https://github.com/hadley/tibble/blob/master/R/rownames.R Oh, and it looks like there is indeed a `column_to_rownames` function there. – Frank Apr 18 '16 at 21:21

3 Answers3

19

You can now use the tibble-package:

tibble::column_to_rownames()
Daniel
  • 7,252
  • 6
  • 26
  • 38
7

This provides NSE & standard eval functions:

library(dplyr)

df <- data_frame(a=sample(letters, 4), b=c(1:4), c=c(5:8))

reset_rownames <- function(df, col="rowname") {
  stopifnot(is.data.frame(df))
  col <- as.character(substitute(col))
  reset_rownames_(df, col)
}

reset_rownames_ <- function(df, col="rowname") {
  stopifnot(is.data.frame(df))
  nm <- data.frame(df)[, col]
  df <- df[, !(colnames(df) %in% col)]
  rownames(df) <- nm
  df
}

m <- "rowname"

head(as.matrix(reset_rownames(add_rownames(mtcars), "rowname")))
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

head(as.matrix(reset_rownames_(add_rownames(mtcars), m)))
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

Perhaps to_rownames() or set_rownames() makes more sense. ¯\_(ツ)_/¯ YMMV.

hrbrmstr
  • 77,368
  • 11
  • 139
  • 205
  • It's a cool function. Learned a lot about using NSE. Thanks! It would be great if @hadley can comment on possible inclusion of this function to dplyr. – yuk Apr 19 '16 at 14:54
  • This no longer works on tibbles. It throws `Setting row names on a tibble is deprecated.` – Rentrop Mar 05 '17 at 22:01
  • That does not mean it does not work. It's just a deprecation warning. – hrbrmstr Mar 06 '17 at 02:04
1

If you really need a matrix you can just save the character column to a separate variable, drop it, and then create the matrix

library(dplyr)

df <- data_frame(a = sample(letters, 4), b = c(1:4), c = c(5:8))

letters <- df %>% select(a)
a.matrix <- df %>% select(-a) %>% as.matrix

Not sure what you are going to do after that, but this gets you as far as you asked for...

AllanT
  • 923
  • 11
  • 23