Moses
Moses

Reputation: 1484

How would one create variables using lapply?

I have so many subdatasets in the list and so listing each dataset would be cumbersome and very tedious. Is there a way to achieve this using either lapply or purrr? Thanks in advance.

library(dplyr)
mydata <- list(data.frame(
  A = c(1, 2, 3),
  B = c("Test1", "Test2", "Test3")),
  data.frame(
    A = c(10, 21, 30),
    B = c("Test10", "Test24", "Test32")))

names(mydata) <- c("dat1", "dat2")


mydata$dat1 <- mydata$dat1 %>% 
  mutate(id = "dat1")

mydata$dat2 <- mydata$dat2 %>% 
  mutate(id = "dat2")

Upvotes: 2

Views: 565

Answers (5)

TimTeaFan
TimTeaFan

Reputation: 18541

This is a perfect case for purrr::imap.

If mylist is already named:

library(dplyr)
library(purrr)

# if `mydata` is already named:
imap(mydata, ~ mutate(.x, id = .y))

#> $dat1
#>   A     B   id
#> 1 1 Test1 dat1
#> 2 2 Test2 dat1
#> 3 3 Test3 dat1
#> 
#> $dat2
#>    A      B   id
#> 1 10 Test10 dat2
#> 2 21 Test24 dat2
#> 3 30 Test32 dat2

If mydata is not already named we can also use imap:

library(dplyr)
library(purrr)

mydata <- list(data.frame(
  A = c(1, 2, 3),
  B = c("Test1", "Test2", "Test3")),
  data.frame(
    A = c(10, 21, 30),
    B = c("Test10", "Test24", "Test32")))


imap(mydata, ~ mutate(.x, id = glue::glue("dat{.y}")))
#> [[1]]
#>   A     B   id
#> 1 1 Test1 dat1
#> 2 2 Test2 dat1
#> 3 3 Test3 dat1
#> 
#> [[2]]
#>    A      B   id
#> 1 10 Test10 dat2
#> 2 21 Test24 dat2
#> 3 30 Test32 dat2

Created on 2022-01-18 by the reprex package (v2.0.1)

Upvotes: 1

user63230
user63230

Reputation: 4636

This sounds like a like a good time to use imap which is useful for handling names of lists:

purrr::imap(mydata, ~mutate(.x, id = .y))

# $dat1
#   A     B   id
# 1 1 Test1 dat1
# 2 2 Test2 dat1
# 3 3 Test3 dat1

# $dat2
#    A      B   id
# 1 10 Test10 dat2
# 2 21 Test24 dat2
# 3 30 Test32 dat2

Upvotes: 1

maydin
maydin

Reputation: 3755

Another approach with lapply,

invisible(lapply(seq(mydata), function(x) mydata[[x]]['id'] <<-names(mydata[x])))
mydata

gives,

$dat1
  A     B   id
1 1 Test1 dat1
2 2 Test2 dat1
3 3 Test3 dat1

$dat2
   A      B   id
1 10 Test10 dat2
2 21 Test24 dat2
3 30 Test32 dat2

Upvotes: 1

Limey
Limey

Reputation: 12461

This should do the trick:

listNames <- c("dat1", "dat2")
names(mydata) <- listNames
mydata <- lapply(
            listNames,
            function(x) {
              mydata[[x]] %>% mutate(id = x)
            }
          )
names(mydata) <- listNames
mydata
$dat1
  A     B   id
1 1 Test1 dat1
2 2 Test2 dat1
3 3 Test3 dat1

$dat2
   A      B   id
1 10 Test10 dat2
2 21 Test24 dat2
3 30 Test32 dat2

Upvotes: 1

Sotos
Sotos

Reputation: 51582

A base R solution can be to use Map, i.e.

Map(function(x, y)transform(x, id = y), mydata, paste0('dat', seq(length(mydata))))

Upvotes: 1

Related Questions