I'm looking for a way to automatically add new list elements/levels to an existing list:
my real-life use case has several thousand elements to add, so the manual example below for adding two elements is not feasible anymore,
I need a list because that's the format expected by an API I'm trying to access.
Example:
library(tidyverse)
x <- data.frame(id = c(1,2,3),
label = c("label 1", "label 2", "label 3"),
category = c("cat 1", "cat 2", "cat 3"))
x_list <- x %>%
as.list() %>%
transpose()
names <- c("name 1", "name 2")
# Expected final format/output
full_list <- list(list(name = names[1],
info = x_list),
list(name = names[2],
info = x_list))
So I'm looking for a way to create this list of lists, where I "glue together" all values from the names vector with a "copy" ot the x_list.
I'm not that familiar with lists, so struggling quite a bit. I know that the purrr package can do awesome list things, so I'm open/looking forward to a tidyverse approach, although I'm also gladly taking base R. Thanks.
Iterate over names using map or using the same arguments replace map with lapply in which case no packages are needed.
library(purrr)
result <- map(names, function(nm) list(name = nm, info = x_list))
identical(result, full_list)
## [1] TRUE
Related
I have a nested list videos inside the sublist there is element "title" I want to filter and remove all the sublists in which x$title has the words like {trailer, highlights, match}. Can some good soul help me in solving this ?
Here is the Nested List in R
Here is the Sublist
(Sorry for my language) Thanks in advance
Find all the sublists x for which x$title contains any of the forbidden words and remove them.
forbidden <- c("trailer", "highlights", "match")
bad <- sapply(videos, function(x) any(stringr::str_detect(x$title, regex(forbidden, ignore_case = T))))
videos <- videos[-which(bad)]
Making a small sample dataset (See this SO post).
l <- list(
list(id = "a", title = "blabla trailer"),
list(id = "b", title = "keep this one"),
list(id = "c", title = "remove this match"))
To subset list elements based on search patterns we can use some regular expression to find matches those matches. We can use | to search for multiple possibilities.
# base R
l[!sapply(l, function(x){grepl("match|highlight|trailer", x$title)})]
# purrr
library(purrr)
l[!map_lgl(l, ~ grepl("match|highlight|trailer", .x$title))]
[[1]]
[[1]]$id
[1] "b"
[[1]]$title
[1] "keep this one"
Suppose I have
label <- 'My val'
and I try to create the list
Output <- list(
label = pi
)
I get that the name of the first (only) object in the list is "label" but I want "My val".
I understand I can do
names(Output) <- label
But the list is quite long and I'd rather name it in the list function.
No, you can't reference variables for names when using the list() function to create a list. It will just interpret any variable name as name for the entry. But after constructing the list, you can change the names:
label <- 'My val'
Output <- list(pi)
names(Output)=label
Maybe this could help you, but it would've been much better if you could share a more detailed sample as I thought there might be more variable names involved:
label <- 'My val'
Output <- list(
label = pi
)
Output |>
setNames(label)
$`My val`
[1] 3.141593
Another option is lst from dplyr
library(dplyr)
lst(!!label := pi)
#$`My val`
#[1] 3.141593
Context: translate a table from French to English using a table containing corresponding replacements.
Problem: character strings sometimes are very similar, when white space are involved str_replace() does not consider the whole string.
Reproductible example:
library(stringr) #needed for the str_replace_all() function
#datasets
# test is the table indicating corresponding strings
test = data.frame(fr = as.character(c("Autre", "Autres", "Autre encore")),
en = as.character(c("Other", "Others", "Other again")),
stringsAsFactors = FALSE)
# test1 is the table I want to translate
test1 = data.frame(totrans = as.character(c("Autre", "Autres", "Autre encore")),
stringsAsFactors = FALSE)
# here is a function to translate
test2 = str_replace_all(test1$totrans, setNames(test$en, test$fr))
Output:
I get
> test2
[1] "Other" "Others" "Other encore"
Expected result:
> testexpected
[1] "Other" "Others" "Other again"
As you can see, if strings starts the same but there is no whitespace, replacement is a succes (see Other and Others) but when there is a whitespace, it fails ("Autre encore" is replaced by "Other encore" and not by "Other again").
I feel the answer is very obvious but I just can't find out how to solve it... Any suggestion is welcome.
I think you just need word boundaries (i.e. "\\b") around your look ups. It is straightforward to add these with a paste0 call inside str_replace_all.
Note you don't need to include the whole tidyverse for this; the str_replace_all function is part of the stringr package, which is just one of several packages loaded when you call library(tidyverse):
library(stringr)
test = data.frame(fr = as.character(c("Autre", "Autres", "Autre encore")),
en = as.character(c("Other", "Others", "Other again")),
stringsAsFactors = FALSE)
test1 = data.frame(totrans = as.character(c("Autre", "Autres", "Autre encore")),
stringsAsFactors = FALSE)
str_replace_all(test1$totrans, paste0("\\b", test$fr, "\\b"), test$en)
#> [1] "Other" "Others" "Other again"
Created on 2020-05-14 by the reprex package (v0.3.0)
How can I change the variable(column) names in R? I couldn't do it with plyr package or any other data manipulation R package.
You can also make it like this:
df <- data.frame("1", "b", "test")
names(df) <- c("Name 1", "Name 2", "Name 3")
If you want to change the column names:
colnames(DataFrame)[colnames(DataFrame)=="Old Column Name"] <- "New Column Name"
I've a data frame corresponding to the sample below:
df = data.frame(subject=c("Subject A", "Subject B", "Subject C", "Subject D"),id=c(1:4))
I would like to transform this data frame to a list object that could be conveniently implemented in selectInput:
selectInput("subject", "Subject",
choices = #my_new_list )
I would like for the end-user to see the list of subjects in the selection and for the selectInput to return the corresponding numerical value (id).
If I attempt to get my list via:
df <- data.frame(lapply(df, as.character),
stringsAsFactors = FALSE)
df <- as.list(df)
The selectInput drop down menu shows all available options:
I'm only interested in listing subjects and passing the corresponding numerical values.
Use function split:
my_new_list <- split(df$id, df$subject)
my_new_list
#$`Subject A`
#[1] 1
#$`Subject B`
#[1] 2
#$`Subject C`
#[1] 3
#$`Subject D`
#[1] 4
Together with function with:
my_new_list <- with(df, split(id, subject))
For the choices argument, you can use a named list, from the doc:
If elements of the list are named then that name rather than the value
is displayed to the user
To make the named list you could try:
your_choices <- as.list(df$id)
names(your_choices) <- df$subject
And in the app:
selectInput("subject", "Subject",
choices = your_choices )
Use setNames, for example:
selectizeInput('x3', 'X3', choices = setNames(state.abb, state.name))
like in this example http://shiny.rstudio.com/gallery/option-groups-for-selectize-input.html