Selectively modify single element of a list in a list-column (tidy solution)
I want to replace a single element of a list within a list-column with the value from another column:
library(tidyverse)
df <- tibble(a = list(list(number = 1, letter = "a"), list(number = 2, letter = "b")), b = c("c", "d"))
print(df)
#> # A tibble: 2 x 2
#> a b
#> <list> <chr>
#> 1 <list [2]> c
#> 2 <list [2]> d
This is what the output should look like:
df2 <- tibble(a = list(list(number = 1, letter = "c"), list(number = 2, letter = "d")), b = c("c", "d"))
print(df2)
#> # A tibble: 2 x 2
#> a b
#> <list> <chr>
#> 1 <list [2]> c
#> 2 <list [2]> d
I was able to use a for loop and confusing subsetting syntax, but I am wondering if there is a tidy function or more elegant way to accomplish my goal:
for (i in 1:nrow(df)) {
df$a[[i]]$letter <- df$b[[i]]
}
r tidyverse
add a comment |
I want to replace a single element of a list within a list-column with the value from another column:
library(tidyverse)
df <- tibble(a = list(list(number = 1, letter = "a"), list(number = 2, letter = "b")), b = c("c", "d"))
print(df)
#> # A tibble: 2 x 2
#> a b
#> <list> <chr>
#> 1 <list [2]> c
#> 2 <list [2]> d
This is what the output should look like:
df2 <- tibble(a = list(list(number = 1, letter = "c"), list(number = 2, letter = "d")), b = c("c", "d"))
print(df2)
#> # A tibble: 2 x 2
#> a b
#> <list> <chr>
#> 1 <list [2]> c
#> 2 <list [2]> d
I was able to use a for loop and confusing subsetting syntax, but I am wondering if there is a tidy function or more elegant way to accomplish my goal:
for (i in 1:nrow(df)) {
df$a[[i]]$letter <- df$b[[i]]
}
r tidyverse
add a comment |
I want to replace a single element of a list within a list-column with the value from another column:
library(tidyverse)
df <- tibble(a = list(list(number = 1, letter = "a"), list(number = 2, letter = "b")), b = c("c", "d"))
print(df)
#> # A tibble: 2 x 2
#> a b
#> <list> <chr>
#> 1 <list [2]> c
#> 2 <list [2]> d
This is what the output should look like:
df2 <- tibble(a = list(list(number = 1, letter = "c"), list(number = 2, letter = "d")), b = c("c", "d"))
print(df2)
#> # A tibble: 2 x 2
#> a b
#> <list> <chr>
#> 1 <list [2]> c
#> 2 <list [2]> d
I was able to use a for loop and confusing subsetting syntax, but I am wondering if there is a tidy function or more elegant way to accomplish my goal:
for (i in 1:nrow(df)) {
df$a[[i]]$letter <- df$b[[i]]
}
r tidyverse
I want to replace a single element of a list within a list-column with the value from another column:
library(tidyverse)
df <- tibble(a = list(list(number = 1, letter = "a"), list(number = 2, letter = "b")), b = c("c", "d"))
print(df)
#> # A tibble: 2 x 2
#> a b
#> <list> <chr>
#> 1 <list [2]> c
#> 2 <list [2]> d
This is what the output should look like:
df2 <- tibble(a = list(list(number = 1, letter = "c"), list(number = 2, letter = "d")), b = c("c", "d"))
print(df2)
#> # A tibble: 2 x 2
#> a b
#> <list> <chr>
#> 1 <list [2]> c
#> 2 <list [2]> d
I was able to use a for loop and confusing subsetting syntax, but I am wondering if there is a tidy function or more elegant way to accomplish my goal:
for (i in 1:nrow(df)) {
df$a[[i]]$letter <- df$b[[i]]
}
r tidyverse
r tidyverse
asked Jan 20 at 3:51
hlineehlinee
1339
1339
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
We could use a base R approach using mapply
by changing values in letter
element of every list from the corresponding b
element.
df$a <- mapply(function(x, y) {x['letter'] <- y;list(x)}, df$a, df$b)
df$a
#[[1]]
#[[1]]$number
#[1] 1
#[[1]]$letter
#[1] "c"
#[[2]]
#[[2]]$number
#[1] 2
#[[2]]$letter
#[1] "d"
If you are interested in the tidyverse
approach we could use the same logic using map2
library(tidyverse)
df$a <- map2(df$a, df$b, function(x, y) {x['letter'] <- y;x})
Or using a different approach using lapply
do.call("rbind", lapply(seq_len(nrow(df)), function(x) {
df$a[[x]]['letter'] <- df$b[x]
df[x, ]
}))
Could you explain why it is necessary to add list(x) after the assignment statement? I tried it without the list(x) and apparently it replaces the whole list with the variable, but I am not sure how adding list(x) corrects this problem.
– hlinee
Jan 23 at 23:51
1
@hlinee it will return the object which is last inmapply
call. So if you don't returnlist(x)
it will return only the modifiedx['letter']
part and will ignore the remaining part of list which isnumber
in this case.
– Ronak Shah
Jan 24 at 8:32
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%2f54273428%2fselectively-modify-single-element-of-a-list-in-a-list-column-tidy-solution%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
We could use a base R approach using mapply
by changing values in letter
element of every list from the corresponding b
element.
df$a <- mapply(function(x, y) {x['letter'] <- y;list(x)}, df$a, df$b)
df$a
#[[1]]
#[[1]]$number
#[1] 1
#[[1]]$letter
#[1] "c"
#[[2]]
#[[2]]$number
#[1] 2
#[[2]]$letter
#[1] "d"
If you are interested in the tidyverse
approach we could use the same logic using map2
library(tidyverse)
df$a <- map2(df$a, df$b, function(x, y) {x['letter'] <- y;x})
Or using a different approach using lapply
do.call("rbind", lapply(seq_len(nrow(df)), function(x) {
df$a[[x]]['letter'] <- df$b[x]
df[x, ]
}))
Could you explain why it is necessary to add list(x) after the assignment statement? I tried it without the list(x) and apparently it replaces the whole list with the variable, but I am not sure how adding list(x) corrects this problem.
– hlinee
Jan 23 at 23:51
1
@hlinee it will return the object which is last inmapply
call. So if you don't returnlist(x)
it will return only the modifiedx['letter']
part and will ignore the remaining part of list which isnumber
in this case.
– Ronak Shah
Jan 24 at 8:32
add a comment |
We could use a base R approach using mapply
by changing values in letter
element of every list from the corresponding b
element.
df$a <- mapply(function(x, y) {x['letter'] <- y;list(x)}, df$a, df$b)
df$a
#[[1]]
#[[1]]$number
#[1] 1
#[[1]]$letter
#[1] "c"
#[[2]]
#[[2]]$number
#[1] 2
#[[2]]$letter
#[1] "d"
If you are interested in the tidyverse
approach we could use the same logic using map2
library(tidyverse)
df$a <- map2(df$a, df$b, function(x, y) {x['letter'] <- y;x})
Or using a different approach using lapply
do.call("rbind", lapply(seq_len(nrow(df)), function(x) {
df$a[[x]]['letter'] <- df$b[x]
df[x, ]
}))
Could you explain why it is necessary to add list(x) after the assignment statement? I tried it without the list(x) and apparently it replaces the whole list with the variable, but I am not sure how adding list(x) corrects this problem.
– hlinee
Jan 23 at 23:51
1
@hlinee it will return the object which is last inmapply
call. So if you don't returnlist(x)
it will return only the modifiedx['letter']
part and will ignore the remaining part of list which isnumber
in this case.
– Ronak Shah
Jan 24 at 8:32
add a comment |
We could use a base R approach using mapply
by changing values in letter
element of every list from the corresponding b
element.
df$a <- mapply(function(x, y) {x['letter'] <- y;list(x)}, df$a, df$b)
df$a
#[[1]]
#[[1]]$number
#[1] 1
#[[1]]$letter
#[1] "c"
#[[2]]
#[[2]]$number
#[1] 2
#[[2]]$letter
#[1] "d"
If you are interested in the tidyverse
approach we could use the same logic using map2
library(tidyverse)
df$a <- map2(df$a, df$b, function(x, y) {x['letter'] <- y;x})
Or using a different approach using lapply
do.call("rbind", lapply(seq_len(nrow(df)), function(x) {
df$a[[x]]['letter'] <- df$b[x]
df[x, ]
}))
We could use a base R approach using mapply
by changing values in letter
element of every list from the corresponding b
element.
df$a <- mapply(function(x, y) {x['letter'] <- y;list(x)}, df$a, df$b)
df$a
#[[1]]
#[[1]]$number
#[1] 1
#[[1]]$letter
#[1] "c"
#[[2]]
#[[2]]$number
#[1] 2
#[[2]]$letter
#[1] "d"
If you are interested in the tidyverse
approach we could use the same logic using map2
library(tidyverse)
df$a <- map2(df$a, df$b, function(x, y) {x['letter'] <- y;x})
Or using a different approach using lapply
do.call("rbind", lapply(seq_len(nrow(df)), function(x) {
df$a[[x]]['letter'] <- df$b[x]
df[x, ]
}))
edited Jan 20 at 4:54
answered Jan 20 at 4:46
Ronak ShahRonak Shah
38.2k104161
38.2k104161
Could you explain why it is necessary to add list(x) after the assignment statement? I tried it without the list(x) and apparently it replaces the whole list with the variable, but I am not sure how adding list(x) corrects this problem.
– hlinee
Jan 23 at 23:51
1
@hlinee it will return the object which is last inmapply
call. So if you don't returnlist(x)
it will return only the modifiedx['letter']
part and will ignore the remaining part of list which isnumber
in this case.
– Ronak Shah
Jan 24 at 8:32
add a comment |
Could you explain why it is necessary to add list(x) after the assignment statement? I tried it without the list(x) and apparently it replaces the whole list with the variable, but I am not sure how adding list(x) corrects this problem.
– hlinee
Jan 23 at 23:51
1
@hlinee it will return the object which is last inmapply
call. So if you don't returnlist(x)
it will return only the modifiedx['letter']
part and will ignore the remaining part of list which isnumber
in this case.
– Ronak Shah
Jan 24 at 8:32
Could you explain why it is necessary to add list(x) after the assignment statement? I tried it without the list(x) and apparently it replaces the whole list with the variable, but I am not sure how adding list(x) corrects this problem.
– hlinee
Jan 23 at 23:51
Could you explain why it is necessary to add list(x) after the assignment statement? I tried it without the list(x) and apparently it replaces the whole list with the variable, but I am not sure how adding list(x) corrects this problem.
– hlinee
Jan 23 at 23:51
1
1
@hlinee it will return the object which is last in
mapply
call. So if you don't return list(x)
it will return only the modified x['letter']
part and will ignore the remaining part of list which is number
in this case.– Ronak Shah
Jan 24 at 8:32
@hlinee it will return the object which is last in
mapply
call. So if you don't return list(x)
it will return only the modified x['letter']
part and will ignore the remaining part of list which is number
in this case.– Ronak Shah
Jan 24 at 8:32
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%2f54273428%2fselectively-modify-single-element-of-a-list-in-a-list-column-tidy-solution%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