So I have a bunch of intermediate data frame objects that are numbered in my global environment according to their order. i.e. IRIS1_St, IRIS2_Db, IRIS1_Start, IRIS2_FIXAR, IRIS4_Change, IRIS10_bananas
I have worked out how to extract these and return the number of row and number of columns without keeping a list column (see below), and technically I have extracted the column names. But I can't for the life of me work out how to turn this colname column into something that isn't a list so I can then compare the lag value and return a simpler column that shows what's new. I've tried data.table(), data.frame(), as.character() and then a str_replace_all() to turn it into a vector. But nothing seems to work, which seems to be because I suck at using lists!
library(dplyr)
library(purrr)
library(stringr)
IRIS1_St <- iris
IRIS2_Db <- IRIS1_St %>%
mutate(Petal.Length2 = Petal.Length*2)
IRIS3_Sum <- IRIS2_Db %>%
mutate(Sepal.sum = sum(Sepal.Length, Sepal.Width))
IRIS4_Change <- IRIS3_Sum %>%
mutate(SL.Change = Sepal.Length - lag(Sepal.Length)) %>% filter(Petal.Length >=4)
IRIS10_bananas <- IRIS4_Change %>% mutate( bananas = case_when(Sepal.Length >6 ~ "BANANAS!!"))
Obj_Size <- grep("^IRIS",names(.GlobalEnv),value=TRUE) %>%
na.omit() %>%
mget(envir = globalenv()) %>%
{OS <<-.} %>%
map_df(nrow) %>%
pivot_longer(1:max(ncol(.)), names_to = "Obj_name", values_to = "nrow") %>%
left_join(OS %>%
map_df(ncol) %>%
pivot_longer(1:max(ncol(.)), names_to = "Obj_name", values_to = "ncol")
) %>%
data.frame(OS %>%
lapply(colnames) %>%
data.table()) %>%
mutate(number = as.numeric(replace_na(str_extract(Obj_name, "(?i)(?<=IRIS\\D{0,1})\\d+"), 0))) %>%
arrange(number, Obj_name) %>%
select(-number) %>% data.frame() %>%
rename(colnames = '.')
#just to seperate out the colname extraction I've done so far
OST <- OS %>% lapply(colnames) %>% data.table()
to extract what's new I've tried the following, but it's screwing up because of the fact that I've made a list.
Obj_Size_New <- Obj_Size %>%
mutate(lag_col = as.character(lag(colnames)),
new_col = setdiff(as.character(colnames), lag_col))
Expected output is as follows;
Obj_name nrow ncol new_col
1 IRIS1_St 150 5 Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species
2 IRIS2_Db 150 6 Petal.Length2
3 IRIS3_Sum 150 7 Sepal.sum
4 IRIS4_Change 89 8 SL.Change
5 IRIS10_bananas 89 9 bananas
I rewrote the above using the advise from akrun below;
library(dplyr)
library(purrr)
library(stringr)
library(tibble)
Obj_Size <- grep("^IRIS",names(.GlobalEnv),value=TRUE) %>% #ID all objects in GE starting with "IRIS"
na.omit() %>%
mget(envir = globalenv()) %>% #Use base R to get them
{OS <<-.} %>% #create intermediate object in GE to join to later
map_df(nrow) %>% #Map nrow using purrr
pivot_longer(1:max(ncol(.)), names_to = "Obj_name", values_to = "nrow") %>% #pivot so it's readable
left_join(OS %>% #repeat with ncol and join back to dataset
map_df(ncol) %>%
pivot_longer(1:max(ncol(.)), names_to = "Obj_name", values_to = "ncol")
) %>%
left_join(OS %>% #repeat with colnames
map(colnames) %>%
enframe() %>% #create 2 col dataframe
rename(Obj_name = name,
colnames = value)) %>%
mutate(number = as.numeric(replace_na(str_extract(Obj_name, "(?i)(?<=IRIS\\D{0,1})\\d+"), 0))) %>% #extract number after IRIS in object name so we can order correctly even when we get to 10 as when ordered by name with 10 it puts it after 1.
arrange(number, Obj_name) %>%
select(-number) %>%
data.frame() %>%
mutate (new_col = map2_chr(colnames, lag(colnames), ~toString(setdiff(.x, .y)))) #Id changes between colnames and only return anything new.