157

I want to create a vector out of a row of a data frame. But I don't want to have to row and column names. I tried several things... but had no luck.

This is my data frame:

> df <- data.frame(a=c(1,2,4,2),b=c(2,6,2,1),c=c(2.6,8.2,7.5,3))
> df
  a b   c
1 1 2 2.6
2 2 6 8.2
3 4 2 7.5
4 2 1 3.0

I tried:

> newV <- as.vector(df[1,])
> newV
  a b   c
1 1 2 2.6

But I really want something looking like this:

> newV <- c( 1,2,2.6)
> newV
[1] 1.0 2.0 2.6
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
Joko
  • 2,539
  • 3
  • 17
  • 24

6 Answers6

210

When you extract a single row from a data frame you get a one-row data frame. Convert it to a numeric vector:

as.numeric(df[1,])

As @Roland suggests, unlist(df[1,]) will convert the one-row data frame to a numeric vector without dropping the names. Therefore unname(unlist(df[1,])) is another, slightly more explicit way to get to the same result.

As @Josh comments below, if you have a not-completely-numeric (alphabetic, factor, mixed ...) data frame, you need as.character(df[1,]) instead.

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • it might be +1 (or 0 down-votes) to the OP for giving code that illustrated clearly what they wanted even though the text and title of the question were garbled ... – Ben Bolker Jan 23 '13 at 16:45
  • @ChinmayPatil, what are their other options? Their code example certainly makes it look like that's what they want. – Ben Bolker Jan 23 '13 at 16:47
  • @BenBolker see my solution with as.vector(t(df)[,1]) – CHP Jan 23 '13 at 16:48
  • @ChinmayPatil, see my comments. You ended up with the same result as I did. – Ben Bolker Jan 23 '13 at 16:53
  • `as.numeric( )` returns a vector that has substantially smaller size than the return from `unlist( )`. For example, `as.numeric(df[1, ])` has size 72 bytes, but `unlist(df[1, ])` has 400 bytes. – semibruin May 21 '15 at 19:15
  • @semibruin, the difference is due to whether names are retained or not. try `object.size(unname(unlist(df[1,])))` – Ben Bolker May 21 '15 at 19:24
  • 2
    It should be noted that a data frame is already a vector and hence as.vector sees it is a vector of mode "list" and does nothing. To facilitate understanding of the underlying mechanisms try as.vector(df[1,], mode="numeric") which is more illustrative. This is what as.numeric does. –  Feb 26 '16 at 13:47
  • @PatrickT: I think you may have tried `as.numeric(df)` rather than `as.numeric(df[1,])` ? – Ben Bolker Dec 01 '17 at 13:32
  • what you're trying to do here is extract **columns** rather than rows. May I suggest that you post a new question? This is an issue that is likely to widespread confusion (you may want to search for duplicates under "extract columns from tibble" first ...) – Ben Bolker Dec 01 '17 at 14:15
  • Sorry Ben, I just wanted to point out that ``as.numeric()`` and ``unname(unlist())`` are not exact equivalent, didn't mean to cause a stir! – PatrickT Dec 01 '17 at 15:05
  • 1
    no problem. I'm only stating that *for this problem* they give exactly the same answer. – Ben Bolker Dec 01 '17 at 16:48
  • 1
    Might have been changed in the meantime, but today unlist allows dropping names: `identical(unlist(df[1,], use.names = FALSE), as.numeric(df[1,]))` (and btw df still is not a sensible name for a data.frame... ;-)) – Andri Signorell Sep 25 '19 at 13:51
  • `as.character(df[1,])` if the row contains character (or mixed) data – Josh Oct 30 '19 at 14:39
  • I found `as.character()` not working for `data.frame` contains `factor` column: `as.character(data.frame(x = c("A", "B"), y = 1:2)[1, ])`, output is: `[1] "1" "1"` – wm3 Dec 13 '19 at 01:53
59

I recommend unlist, which keeps the names.

unlist(df[1,])
  a   b   c 
1.0 2.0 2.6 

is.vector(unlist(df[1,]))
[1] TRUE

If you don't want a named vector:

unname(unlist(df[1,]))
[1] 1.0 2.0 2.6
Roland
  • 127,288
  • 10
  • 191
  • 288
15

Here is a dplyr based option:

newV = df %>% slice(1) %>% unlist(use.names = FALSE)

# or slightly different:
newV = df %>% slice(1) %>% unlist() %>% unname()
sbha
  • 9,802
  • 2
  • 74
  • 62
8

If you don't want to change to numeric you can try this.

> as.vector(t(df)[,1])
[1] 1.0 2.0 2.6
CHP
  • 16,981
  • 4
  • 38
  • 57
  • 3
    this doesn't make much sense to me: `str(as.vector(t(df)[,1]))` is `num [1:3] 1 2 2.6`, i.e. your code **does** convert the results to a numeric vector ... – Ben Bolker Jan 23 '13 at 16:48
  • 2
    specifically, when you use `t(df)` R coerces the data frame to a matrix, in this case a numeric matrix because all the elements are numeric. Then `[,1]` extracts the first column (a numeric vector, because the redundant dimension is automatically dropped). `as.vector()` just drops the names (which you could also do with `unname()`). – Ben Bolker Jan 23 '13 at 16:50
  • It seems to work for characters as well. But you are right about coersion. FWIW, my solution will work on character data frames as well.. with caveat of all the data being converted to character – CHP Jan 23 '13 at 16:54
  • 2
    I would say that the `unname(unlist(x))` solution is a little better (more efficient and more transparent). – Ben Bolker Jan 23 '13 at 16:55
  • `as.vector(t(df)[,1])` I love it ! Exactly what I need it ! – Uther Pendragon Jun 15 '15 at 03:47
  • if one column is `factor`, `unlist` convert to it to an index. – user3226167 May 25 '17 at 08:31
5

Note that you have to be careful if your row contains a factor. Here is an example:

df_1 = data.frame(V1 = factor(11:15),
                  V2 = 21:25)
df_1[1,] %>% as.numeric() # you expect 11 21 but it returns 
[1] 1 21

Here is another example (by default data.frame() converts characters to factors)

df_2 = data.frame(V1 = letters[1:5],
                  V2 = 1:5)
df_2[3,] %>% as.numeric() # you expect to obtain c 3 but it returns
[1] 3 3
df_2[3,] %>% as.character() # this won't work neither
[1] "3" "3"

To prevent this behavior, you need to take care of the factor, before extracting it:

df_1$V1 = df_1$V1 %>% as.character() %>% as.numeric()
df_2$V1 = df_2$V1 %>% as.character()
df_1[1,] %>% as.numeric()
[1] 11  21
df_2[3,] %>% as.character()
[1] "c" "3"
Rtist
  • 3,825
  • 2
  • 31
  • 40
-6

Columns of data frames are already vectors, you just have to pull them out. Note that you place the column you want after the comma, not before it:

> newV <- df[,1]
> newV
[1] 1 2 4 2

If you actually want a row, then do what Ben said and please use words correctly in the future.

Jonathan Christensen
  • 3,756
  • 1
  • 19
  • 16