Select variables from list of tibbles using names in each tibble
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I have a list of tibbles or data frames (each one with a name in the list) and I want to: (1) create new columns with the same name long.col in each tibble from variables with different names; (2) do this by matching from another tibble with the key linking tibble name and column name in each tibble and finally; (3) binding rows for all the newly created columns with the same name long.col in each tibble as well as identifying the original tibble where they came from.
I would like to do this preferably using tidyverse functions. Here is a an example of both: a) the list of tibbles; b) the key tibble identifying tibble names and variables to select in each one
df1 <- tibble(v1 = c(rep("A", 5), rep("B", 5)),
v2 = 1:10)
df2 <- tibble(v1 = c(rep("C", 6), rep("D", 6)),
v3 = 11:22)
df3 <- tibble(v1 = c(rep("E", 4), rep("F", 4)),
v4 = 23:30)
list.df <- list(df1, df2, df3)
names(list.df) <- c("data1", "data2", "data3")
key <- tibble(data = c("data1", "data2", "data3"),
vars = c("v2", "v3", "v4"))
The final output should look like:
final.df <- tibble(data = c(rep("data1", 10), rep("data2", 12), rep("data3", 8)),
long.col = 1:30)
I need to do this in a much longer list using multiple columns, so it is not feasible to do it separately for each column in each tibble.
r list select data-binding tibble
add a comment |
I have a list of tibbles or data frames (each one with a name in the list) and I want to: (1) create new columns with the same name long.col in each tibble from variables with different names; (2) do this by matching from another tibble with the key linking tibble name and column name in each tibble and finally; (3) binding rows for all the newly created columns with the same name long.col in each tibble as well as identifying the original tibble where they came from.
I would like to do this preferably using tidyverse functions. Here is a an example of both: a) the list of tibbles; b) the key tibble identifying tibble names and variables to select in each one
df1 <- tibble(v1 = c(rep("A", 5), rep("B", 5)),
v2 = 1:10)
df2 <- tibble(v1 = c(rep("C", 6), rep("D", 6)),
v3 = 11:22)
df3 <- tibble(v1 = c(rep("E", 4), rep("F", 4)),
v4 = 23:30)
list.df <- list(df1, df2, df3)
names(list.df) <- c("data1", "data2", "data3")
key <- tibble(data = c("data1", "data2", "data3"),
vars = c("v2", "v3", "v4"))
The final output should look like:
final.df <- tibble(data = c(rep("data1", 10), rep("data2", 12), rep("data3", 8)),
long.col = 1:30)
I need to do this in a much longer list using multiple columns, so it is not feasible to do it separately for each column in each tibble.
r list select data-binding tibble
add a comment |
I have a list of tibbles or data frames (each one with a name in the list) and I want to: (1) create new columns with the same name long.col in each tibble from variables with different names; (2) do this by matching from another tibble with the key linking tibble name and column name in each tibble and finally; (3) binding rows for all the newly created columns with the same name long.col in each tibble as well as identifying the original tibble where they came from.
I would like to do this preferably using tidyverse functions. Here is a an example of both: a) the list of tibbles; b) the key tibble identifying tibble names and variables to select in each one
df1 <- tibble(v1 = c(rep("A", 5), rep("B", 5)),
v2 = 1:10)
df2 <- tibble(v1 = c(rep("C", 6), rep("D", 6)),
v3 = 11:22)
df3 <- tibble(v1 = c(rep("E", 4), rep("F", 4)),
v4 = 23:30)
list.df <- list(df1, df2, df3)
names(list.df) <- c("data1", "data2", "data3")
key <- tibble(data = c("data1", "data2", "data3"),
vars = c("v2", "v3", "v4"))
The final output should look like:
final.df <- tibble(data = c(rep("data1", 10), rep("data2", 12), rep("data3", 8)),
long.col = 1:30)
I need to do this in a much longer list using multiple columns, so it is not feasible to do it separately for each column in each tibble.
r list select data-binding tibble
I have a list of tibbles or data frames (each one with a name in the list) and I want to: (1) create new columns with the same name long.col in each tibble from variables with different names; (2) do this by matching from another tibble with the key linking tibble name and column name in each tibble and finally; (3) binding rows for all the newly created columns with the same name long.col in each tibble as well as identifying the original tibble where they came from.
I would like to do this preferably using tidyverse functions. Here is a an example of both: a) the list of tibbles; b) the key tibble identifying tibble names and variables to select in each one
df1 <- tibble(v1 = c(rep("A", 5), rep("B", 5)),
v2 = 1:10)
df2 <- tibble(v1 = c(rep("C", 6), rep("D", 6)),
v3 = 11:22)
df3 <- tibble(v1 = c(rep("E", 4), rep("F", 4)),
v4 = 23:30)
list.df <- list(df1, df2, df3)
names(list.df) <- c("data1", "data2", "data3")
key <- tibble(data = c("data1", "data2", "data3"),
vars = c("v2", "v3", "v4"))
The final output should look like:
final.df <- tibble(data = c(rep("data1", 10), rep("data2", 12), rep("data3", 8)),
long.col = 1:30)
I need to do this in a much longer list using multiple columns, so it is not feasible to do it separately for each column in each tibble.
r list select data-binding tibble
r list select data-binding tibble
asked Nov 25 '18 at 4:49
CrimcCrimc
165
165
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
You can use map2 here
library(purrr)
library(tibble)
out <- map2_df(.x = list.df,
.y = names(list.df),
.f = ~ {
temp <- key[["vars"]][key[['data']] == .y]
tibble(data = .y, long.col = .x[[temp]])
})
Check the output
identical(final.df, out)
#[1] TRUE
I actually found your 1st answer (withpmap()) even more elegant (because more compact and not requiring the assignment of temporary objects). May I ask you why decided to usemap2()instead? Thank you
– prosoitos
Nov 25 '18 at 18:47
1
@prosoitos Thanks for your comment. I changed the answer because withpmap- as you probably know - we iterated overlist.df,names(list.df)andkey[['vars']]in parallel. We got the correct output because the elements inkey[['vars']]are in the correct order. ...
– markus
Nov 25 '18 at 18:58
1
Thank you! I suspected that you had changed it to make it more general, but I wasn't sure. I was about to post an answer using purrr yesterday when you posted yours, but mine was not nearly as elegant and involved creating a function first. So both your answers were very educative for me :)
– prosoitos
Nov 25 '18 at 19:01
... if we were to change the order of the rows inkeywe'd get an error: "Callrlang::last_error()to see a backtrace". Best
– markus
Nov 25 '18 at 19:20
add a comment |
The first step in the problem you have stated is to dynamically pick the variable name from the key table, and assign the value in the respective dataframe. This can be done by first defining a function which returns the base variable name (for long.col) based on the data frame.
getBaseVar <- function(dfName, keyTibble){
varToBeTransformed <- keyTibble %>% dplyr::filter(data == (!!dfName)) %>%
dplyr::select(vars) %>% dplyr::first() %>%
rlang::sym(.)
return(varToBeTransformed)
}
This function returns the required variable name as a symbol. This can then be passed to the dplyr::mutate function. In order to do this dynamically for all dataframes present in the list, we pass the named list of dataframes to the purrr::imap function, through which both the list element (dataframe in your case) and the name of the list element can be accessed.
list.df.transformed <- purrr::imap(list.df, function(df, name){
df %>% dplyr::mutate( long.col := !!getBaseVar(name, key))
})
Finally, the output you desire can be created by passing this list of transformed dataframes through purrr::imap once again, and extracting the necessary data (i.e. the long.col column and the variable with a repeating value of the name of the dataframe). After extraction, passing it to the dplyr::bind_rows function returns the desired data frame.
final.df <- tibble(data = character(), long.col = numeric())
purrr::imap(list.df.transformed, function(df, name){
repeatedNameCol <- tibble(data = rep(name, nrow(df)))
dataToBind <- df %>% dplyr::select(long.col) %>%
dplyr::bind_cols(repeatedNameCol)
return(dataToBind)
}) %>% dplyr::bind_rows(.) -> final.df
Hope this helps!
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53464733%2fselect-variables-from-list-of-tibbles-using-names-in-each-tibble%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use map2 here
library(purrr)
library(tibble)
out <- map2_df(.x = list.df,
.y = names(list.df),
.f = ~ {
temp <- key[["vars"]][key[['data']] == .y]
tibble(data = .y, long.col = .x[[temp]])
})
Check the output
identical(final.df, out)
#[1] TRUE
I actually found your 1st answer (withpmap()) even more elegant (because more compact and not requiring the assignment of temporary objects). May I ask you why decided to usemap2()instead? Thank you
– prosoitos
Nov 25 '18 at 18:47
1
@prosoitos Thanks for your comment. I changed the answer because withpmap- as you probably know - we iterated overlist.df,names(list.df)andkey[['vars']]in parallel. We got the correct output because the elements inkey[['vars']]are in the correct order. ...
– markus
Nov 25 '18 at 18:58
1
Thank you! I suspected that you had changed it to make it more general, but I wasn't sure. I was about to post an answer using purrr yesterday when you posted yours, but mine was not nearly as elegant and involved creating a function first. So both your answers were very educative for me :)
– prosoitos
Nov 25 '18 at 19:01
... if we were to change the order of the rows inkeywe'd get an error: "Callrlang::last_error()to see a backtrace". Best
– markus
Nov 25 '18 at 19:20
add a comment |
You can use map2 here
library(purrr)
library(tibble)
out <- map2_df(.x = list.df,
.y = names(list.df),
.f = ~ {
temp <- key[["vars"]][key[['data']] == .y]
tibble(data = .y, long.col = .x[[temp]])
})
Check the output
identical(final.df, out)
#[1] TRUE
I actually found your 1st answer (withpmap()) even more elegant (because more compact and not requiring the assignment of temporary objects). May I ask you why decided to usemap2()instead? Thank you
– prosoitos
Nov 25 '18 at 18:47
1
@prosoitos Thanks for your comment. I changed the answer because withpmap- as you probably know - we iterated overlist.df,names(list.df)andkey[['vars']]in parallel. We got the correct output because the elements inkey[['vars']]are in the correct order. ...
– markus
Nov 25 '18 at 18:58
1
Thank you! I suspected that you had changed it to make it more general, but I wasn't sure. I was about to post an answer using purrr yesterday when you posted yours, but mine was not nearly as elegant and involved creating a function first. So both your answers were very educative for me :)
– prosoitos
Nov 25 '18 at 19:01
... if we were to change the order of the rows inkeywe'd get an error: "Callrlang::last_error()to see a backtrace". Best
– markus
Nov 25 '18 at 19:20
add a comment |
You can use map2 here
library(purrr)
library(tibble)
out <- map2_df(.x = list.df,
.y = names(list.df),
.f = ~ {
temp <- key[["vars"]][key[['data']] == .y]
tibble(data = .y, long.col = .x[[temp]])
})
Check the output
identical(final.df, out)
#[1] TRUE
You can use map2 here
library(purrr)
library(tibble)
out <- map2_df(.x = list.df,
.y = names(list.df),
.f = ~ {
temp <- key[["vars"]][key[['data']] == .y]
tibble(data = .y, long.col = .x[[temp]])
})
Check the output
identical(final.df, out)
#[1] TRUE
edited Nov 25 '18 at 10:57
answered Nov 25 '18 at 7:45
markusmarkus
15.9k11336
15.9k11336
I actually found your 1st answer (withpmap()) even more elegant (because more compact and not requiring the assignment of temporary objects). May I ask you why decided to usemap2()instead? Thank you
– prosoitos
Nov 25 '18 at 18:47
1
@prosoitos Thanks for your comment. I changed the answer because withpmap- as you probably know - we iterated overlist.df,names(list.df)andkey[['vars']]in parallel. We got the correct output because the elements inkey[['vars']]are in the correct order. ...
– markus
Nov 25 '18 at 18:58
1
Thank you! I suspected that you had changed it to make it more general, but I wasn't sure. I was about to post an answer using purrr yesterday when you posted yours, but mine was not nearly as elegant and involved creating a function first. So both your answers were very educative for me :)
– prosoitos
Nov 25 '18 at 19:01
... if we were to change the order of the rows inkeywe'd get an error: "Callrlang::last_error()to see a backtrace". Best
– markus
Nov 25 '18 at 19:20
add a comment |
I actually found your 1st answer (withpmap()) even more elegant (because more compact and not requiring the assignment of temporary objects). May I ask you why decided to usemap2()instead? Thank you
– prosoitos
Nov 25 '18 at 18:47
1
@prosoitos Thanks for your comment. I changed the answer because withpmap- as you probably know - we iterated overlist.df,names(list.df)andkey[['vars']]in parallel. We got the correct output because the elements inkey[['vars']]are in the correct order. ...
– markus
Nov 25 '18 at 18:58
1
Thank you! I suspected that you had changed it to make it more general, but I wasn't sure. I was about to post an answer using purrr yesterday when you posted yours, but mine was not nearly as elegant and involved creating a function first. So both your answers were very educative for me :)
– prosoitos
Nov 25 '18 at 19:01
... if we were to change the order of the rows inkeywe'd get an error: "Callrlang::last_error()to see a backtrace". Best
– markus
Nov 25 '18 at 19:20
I actually found your 1st answer (with
pmap()) even more elegant (because more compact and not requiring the assignment of temporary objects). May I ask you why decided to use map2() instead? Thank you– prosoitos
Nov 25 '18 at 18:47
I actually found your 1st answer (with
pmap()) even more elegant (because more compact and not requiring the assignment of temporary objects). May I ask you why decided to use map2() instead? Thank you– prosoitos
Nov 25 '18 at 18:47
1
1
@prosoitos Thanks for your comment. I changed the answer because with
pmap - as you probably know - we iterated over list.df, names(list.df) and key[['vars']] in parallel. We got the correct output because the elements in key[['vars']] are in the correct order. ...– markus
Nov 25 '18 at 18:58
@prosoitos Thanks for your comment. I changed the answer because with
pmap - as you probably know - we iterated over list.df, names(list.df) and key[['vars']] in parallel. We got the correct output because the elements in key[['vars']] are in the correct order. ...– markus
Nov 25 '18 at 18:58
1
1
Thank you! I suspected that you had changed it to make it more general, but I wasn't sure. I was about to post an answer using purrr yesterday when you posted yours, but mine was not nearly as elegant and involved creating a function first. So both your answers were very educative for me :)
– prosoitos
Nov 25 '18 at 19:01
Thank you! I suspected that you had changed it to make it more general, but I wasn't sure. I was about to post an answer using purrr yesterday when you posted yours, but mine was not nearly as elegant and involved creating a function first. So both your answers were very educative for me :)
– prosoitos
Nov 25 '18 at 19:01
... if we were to change the order of the rows in
key we'd get an error: "Call rlang::last_error() to see a backtrace". Best– markus
Nov 25 '18 at 19:20
... if we were to change the order of the rows in
key we'd get an error: "Call rlang::last_error() to see a backtrace". Best– markus
Nov 25 '18 at 19:20
add a comment |
The first step in the problem you have stated is to dynamically pick the variable name from the key table, and assign the value in the respective dataframe. This can be done by first defining a function which returns the base variable name (for long.col) based on the data frame.
getBaseVar <- function(dfName, keyTibble){
varToBeTransformed <- keyTibble %>% dplyr::filter(data == (!!dfName)) %>%
dplyr::select(vars) %>% dplyr::first() %>%
rlang::sym(.)
return(varToBeTransformed)
}
This function returns the required variable name as a symbol. This can then be passed to the dplyr::mutate function. In order to do this dynamically for all dataframes present in the list, we pass the named list of dataframes to the purrr::imap function, through which both the list element (dataframe in your case) and the name of the list element can be accessed.
list.df.transformed <- purrr::imap(list.df, function(df, name){
df %>% dplyr::mutate( long.col := !!getBaseVar(name, key))
})
Finally, the output you desire can be created by passing this list of transformed dataframes through purrr::imap once again, and extracting the necessary data (i.e. the long.col column and the variable with a repeating value of the name of the dataframe). After extraction, passing it to the dplyr::bind_rows function returns the desired data frame.
final.df <- tibble(data = character(), long.col = numeric())
purrr::imap(list.df.transformed, function(df, name){
repeatedNameCol <- tibble(data = rep(name, nrow(df)))
dataToBind <- df %>% dplyr::select(long.col) %>%
dplyr::bind_cols(repeatedNameCol)
return(dataToBind)
}) %>% dplyr::bind_rows(.) -> final.df
Hope this helps!
add a comment |
The first step in the problem you have stated is to dynamically pick the variable name from the key table, and assign the value in the respective dataframe. This can be done by first defining a function which returns the base variable name (for long.col) based on the data frame.
getBaseVar <- function(dfName, keyTibble){
varToBeTransformed <- keyTibble %>% dplyr::filter(data == (!!dfName)) %>%
dplyr::select(vars) %>% dplyr::first() %>%
rlang::sym(.)
return(varToBeTransformed)
}
This function returns the required variable name as a symbol. This can then be passed to the dplyr::mutate function. In order to do this dynamically for all dataframes present in the list, we pass the named list of dataframes to the purrr::imap function, through which both the list element (dataframe in your case) and the name of the list element can be accessed.
list.df.transformed <- purrr::imap(list.df, function(df, name){
df %>% dplyr::mutate( long.col := !!getBaseVar(name, key))
})
Finally, the output you desire can be created by passing this list of transformed dataframes through purrr::imap once again, and extracting the necessary data (i.e. the long.col column and the variable with a repeating value of the name of the dataframe). After extraction, passing it to the dplyr::bind_rows function returns the desired data frame.
final.df <- tibble(data = character(), long.col = numeric())
purrr::imap(list.df.transformed, function(df, name){
repeatedNameCol <- tibble(data = rep(name, nrow(df)))
dataToBind <- df %>% dplyr::select(long.col) %>%
dplyr::bind_cols(repeatedNameCol)
return(dataToBind)
}) %>% dplyr::bind_rows(.) -> final.df
Hope this helps!
add a comment |
The first step in the problem you have stated is to dynamically pick the variable name from the key table, and assign the value in the respective dataframe. This can be done by first defining a function which returns the base variable name (for long.col) based on the data frame.
getBaseVar <- function(dfName, keyTibble){
varToBeTransformed <- keyTibble %>% dplyr::filter(data == (!!dfName)) %>%
dplyr::select(vars) %>% dplyr::first() %>%
rlang::sym(.)
return(varToBeTransformed)
}
This function returns the required variable name as a symbol. This can then be passed to the dplyr::mutate function. In order to do this dynamically for all dataframes present in the list, we pass the named list of dataframes to the purrr::imap function, through which both the list element (dataframe in your case) and the name of the list element can be accessed.
list.df.transformed <- purrr::imap(list.df, function(df, name){
df %>% dplyr::mutate( long.col := !!getBaseVar(name, key))
})
Finally, the output you desire can be created by passing this list of transformed dataframes through purrr::imap once again, and extracting the necessary data (i.e. the long.col column and the variable with a repeating value of the name of the dataframe). After extraction, passing it to the dplyr::bind_rows function returns the desired data frame.
final.df <- tibble(data = character(), long.col = numeric())
purrr::imap(list.df.transformed, function(df, name){
repeatedNameCol <- tibble(data = rep(name, nrow(df)))
dataToBind <- df %>% dplyr::select(long.col) %>%
dplyr::bind_cols(repeatedNameCol)
return(dataToBind)
}) %>% dplyr::bind_rows(.) -> final.df
Hope this helps!
The first step in the problem you have stated is to dynamically pick the variable name from the key table, and assign the value in the respective dataframe. This can be done by first defining a function which returns the base variable name (for long.col) based on the data frame.
getBaseVar <- function(dfName, keyTibble){
varToBeTransformed <- keyTibble %>% dplyr::filter(data == (!!dfName)) %>%
dplyr::select(vars) %>% dplyr::first() %>%
rlang::sym(.)
return(varToBeTransformed)
}
This function returns the required variable name as a symbol. This can then be passed to the dplyr::mutate function. In order to do this dynamically for all dataframes present in the list, we pass the named list of dataframes to the purrr::imap function, through which both the list element (dataframe in your case) and the name of the list element can be accessed.
list.df.transformed <- purrr::imap(list.df, function(df, name){
df %>% dplyr::mutate( long.col := !!getBaseVar(name, key))
})
Finally, the output you desire can be created by passing this list of transformed dataframes through purrr::imap once again, and extracting the necessary data (i.e. the long.col column and the variable with a repeating value of the name of the dataframe). After extraction, passing it to the dplyr::bind_rows function returns the desired data frame.
final.df <- tibble(data = character(), long.col = numeric())
purrr::imap(list.df.transformed, function(df, name){
repeatedNameCol <- tibble(data = rep(name, nrow(df)))
dataToBind <- df %>% dplyr::select(long.col) %>%
dplyr::bind_cols(repeatedNameCol)
return(dataToBind)
}) %>% dplyr::bind_rows(.) -> final.df
Hope this helps!
answered Nov 25 '18 at 8:06
Naren SrinivasanNaren Srinivasan
314
314
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53464733%2fselect-variables-from-list-of-tibbles-using-names-in-each-tibble%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown