rimorob
rimorob

Reputation: 654

Select data frame values row-wise using a variable of column names

Suppose I have a data frame that looks like this:

dframe = data.frame(x = c(1, 2, 3), y = c(4, 5, 6))
#   x y
# 1 1 4
# 2 2 5
# 3 3 6

And a vector of column names, one per row of the data frame:

colname = c('x', 'y', 'x')

For each row of the data frame, I would like to select the value from the corresponding column in the vector. Something similar to dframe[, colname] but for each row.

Thus, I want to obtain c(1, 5, 3) (i.e. row 1: col "x"; row 2: col "y"; row 3: col "x")

Upvotes: 5

Views: 3495

Answers (2)

thelatemail
thelatemail

Reputation: 93938

My favourite old matrix-indexing will take care of this. Just pass a 2-column matrix with the respective row/column index:

rownames(dframe) <- seq_len(nrow(dframe))
dframe[cbind(rownames(dframe),colname)]
#[1] 1 5 3

Or, if you don't want to add rownames:

dframe[cbind(seq_len(nrow(dframe)), match(colname,names(dframe)))]
#[1] 1 5 3

Upvotes: 5

MKR
MKR

Reputation: 20095

One can use mapply to pass arguments for rownumber (of dframe) and vector for column name (for each row) to return specific column value.

The solution using mapply can be as:

dframe = data.frame(x = c(1, 2, 3), y = c(4, 5, 6))
colname = c('x', 'y', 'x')

mapply(function(x,y)dframe[x,y],1:nrow(dframe),  colname)

#[1] 1 5 3

Although, the next option may not be very intuitive but if someone wants a solution in dplyr chain then a way using gather can be as:

library(tidyverse)

data.frame(colname = c('x', 'y', 'x'), stringsAsFactors = FALSE) %>%
  rownames_to_column() %>%
  left_join(dframe %>% rownames_to_column() %>%
              gather(colname, value, -rowname), 
            by = c("rowname", "colname" )) %>%
  select(rowname, value)

#   rowname value
# 1       1     1
# 2       2     5
# 3       3     3

Upvotes: 1

Related Questions