Reputation: 59
Using tidyverse
, I would like to add a new column in which contains the value of one column where the column name equals a value of another column.
I know the explanation is kind of confusing, so using a simple table for example:
| Name | ID | A01 | A02 | A03 | A04 | A05 | new_column |
| ---- | -- | ----| --- | --- | --- | --- | ---------- |
| a | A01| 2 | 3 | 1 | 4 | 6 | 2 |
| b | A03| 3.4 | 4.5 | 2.2 | 3.6 | 7.2 | 2.2 |
| c | A02| 1.3 | 2.0 | 4.4 | 6.5 | 9.2 | 2.0 |
| d | A05| 0.8 | 7.6 | 3.3 | 4.5 | 1.1 | 1.1 |
Any ideas for adding in column 'new_column' when the original data name is d
, by using a code somewhat similar to
d %>% mutate(new_column = )
?
Thanks is advance :)
Upvotes: 1
Views: 1387
Reputation: 887118
We may use cur_data()
library(dplyr)
df %>%
rowwise %>%
mutate(new_column = cur_data()[[cur_data()$ID]]) %>%
ungroup
# A tibble: 4 × 8
Name ID A01 A02 A03 A04 A05 new_column
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 a A01 2 3 1 4 6 2
2 b A03 3.4 4.5 2.2 3.6 7.2 2.2
3 c A02 1.3 2 4.4 6.5 9.2 2
4 d A05 0.8 7.6 3.3 4.5 1.1 1.1
Upvotes: 2
Reputation: 78927
We can use map2_dbl
from purrr
:
library(dplyr)
library(purrr)
df %>%
mutate(new_column = map2_dbl(row_number(),ID,~df[.x,.y]))
output:
Name ID A01 A02 A03 A04 A05 new_column
1 a A01 2.0 3.0 1.0 4.0 6.0 2.0
2 b A03 3.4 4.5 2.2 3.6 7.2 2.2
3 c A02 1.3 2.0 4.4 6.5 9.2 2.0
4 d A05 0.8 7.6 3.3 4.5 1.1 1.1
data:
df <- structure(list(Name = c("a", "b", "c", "d"), ID = c("A01", "A03",
"A02", "A05"), A01 = c(2, 3.4, 1.3, 0.8), A02 = c(3, 4.5, 2,
7.6), A03 = c(1, 2.2, 4.4, 3.3), A04 = c(4, 3.6, 6.5, 4.5), A05 = c(6,
7.2, 9.2, 1.1)), class = "data.frame", row.names = c(NA, -4L))
Upvotes: 2
Reputation: 1381
You can use the match function in R to match the values of ID
with column names.
df_new <- df %>%
mutate(new_column = as.numeric(df[cbind(1:4, match(df$ID, names(df)))]))
Here's the output of df_new
:
Name ID A01 A02 A03 A04 A05 new_column
1 a A01 2.0 3.0 1.0 4.0 6.0 2.0
2 b A03 3.4 4.5 2.2 3.6 7.2 2.2
3 c A02 1.3 2.0 4.4 6.5 9.2 2.0
4 d A05 0.8 7.6 3.3 4.5 1.1 1.1
You can see this post for further information.
Upvotes: 2
Reputation: 8880
library(tidyverse)
df %>%
pivot_longer(-c(Name, ID)) %>%
transmute(Name, ID, new_column = ifelse(ID == name, value, NA_real_)) %>%
drop_na(new_column) %>%
left_join(df)
Upvotes: 1
Reputation: 4414
This syntax is a bit strange, but it works.
d$new_column <- d[unique(d$ID)][cbind(1:nrow(d), match(d$i, unique(d$ID)))]
This is similar to Vishal's answer, but it ensures the variable type of new_column
is correct (their answer may give you character values instead of numeric values in new_column
).
Upvotes: 0