Selectively modify single element of a list in a list-column (tidy solution)












0















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]]
}









share|improve this question



























    0















    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]]
    }









    share|improve this question

























      0












      0








      0








      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]]
      }









      share|improve this question














      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 20 at 3:51









      hlineehlinee

      1339




      1339
























          1 Answer
          1






          active

          oldest

          votes


















          1














          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, ]
          }))





          share|improve this answer


























          • 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 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













          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
          });


          }
          });














          draft saved

          draft discarded


















          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









          1














          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, ]
          }))





          share|improve this answer


























          • 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 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


















          1














          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, ]
          }))





          share|improve this answer


























          • 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 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
















          1












          1








          1







          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, ]
          }))





          share|improve this answer















          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, ]
          }))






          share|improve this answer














          share|improve this answer



          share|improve this answer








          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 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





















          • 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 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



















          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




















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          Liquibase includeAll doesn't find base path

          How to use setInterval in EJS file?

          Petrus Granier-Deferre