How to loop dataframe in R - r

I want to get data from IMF.However the API data is limited
Therefor I get the data by continent.
How to loop the dateframe? (The data can get from "Before loop part",load data from api)
The reference cannot work.https://stackoverflow.com/questions/25284539/loop-over-a-string-variable-in-r
Before the loop
library(imfr)
library(countrycode)
data(codelist)
country_set <- codelist
country_set<- country_set %>%
select(country.name.en , iso2c, iso3c, imf, continent, region) %>% filter(!is.na(imf) & !is.na(iso2c))
africa_iso2<- country_set$iso2c[country_set$continent=="Africa"]
asia_iso2<- country_set$iso2c[country_set$continent=="Asia"]
americas_iso2<- country_set$iso2c[country_set$continent=="Americas"]
europe_iso2<- country_set$iso2c[country_set$continent=="Europe"]
oceania_iso2<- country_set$iso2c[country_set$continent=="Oceania"]
loop part
continent <- c("africa", "asia", "americas","europe","oceania")
for(i in 1:length(continent)){
var <- paste0("gdp_nsa_xdc_", continent[i])
var1 <- paste0(continent[i],"_iso2")
[[var]]<- imf_data(database_id = "IFS" , indicator = c("NGDP_NSA_XDC"),country =[[var1]],start = 2010, end = 2022,return_raw = TRUE)
[[var]]<- [[var]]$CompactData$DataSet$Series
}
data sample is
list(CompactData = list(`#xmlns:xsi` = "http://www.w3.org/2001/XMLSchema-instance",
`#xmlns:xsd` = "http://www.w3.org/2001/XMLSchema", `#xsi:schemaLocation` = "http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message https://registry.sdmx.org/schemas/v2_0/SDMXMessage.xsd http://dataservices.imf.org/compact/IFS http://dataservices.imf.org/compact/IFS.xsd",
`#xmlns` = "http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message",
Header = list(ID = "18e0aeae-09ec-4dfe-ab72-60aa16aaea84",
Test = "false", Prepared = "2022-10-19T12:02:28", Sender = list(
`#id` = "1C0", Name = list(`#xml:lang` = "en", `#text` = "IMF"),
Contact = list(URI = "http://www.imf.org", Telephone = "+ 1 (202) 623-6220")),
Receiver = list(`#id` = "ZZZ"), DataSetID = "IFS"), DataSet = list(
`#xmlns` = "http://dataservices.imf.org/compact/IFS",
Series = list(`#FREQ` = "Q", `#REF_AREA` = "US", `#INDICATOR` = "NGDP_NSA_XDC",
`#UNIT_MULT` = "6", `#TIME_FORMAT` = "P3M", Obs = structure(list(
`#TIME_PERIOD` = c("2020-Q1", "2020-Q2", "2020-Q3",
"2020-Q4", "2021-Q1", "2021-Q2", "2021-Q3", "2021-Q4",
"2022-Q1", "2022-Q2"), `#OBS_VALUE` = c("5254152",
"4930197", "5349433", "5539370", "5444406", "5784816",
"5883177", "6203369", "6010733", "6352982")), class = "data.frame", row.names = c(NA,
10L))))))

I suggest you create a list first, to which you will assign the value you want your loop to create. The following code creates a named list, and then at the end of the loop, assigns the value of each iteration to that named list:
continent <-
sapply(c("africa", "asia", "americas","europe","oceania"),
c, simplify = FALSE, USE.NAMES = TRUE)
for(i in seq_len(length(continent))) {
var <- paste0("gdp_nsa_xdc_", continent[i])
var1 <- get(paste0(continent[i],"_iso2"))
var <- imf_data(database_id = "IFS" , indicator = c("NGDP_NSA_XDC"),
country = var1, start = 2010, end = 2022,
return_raw = TRUE)
continent[[i]] <- var$CompactData$DataSet$Series
}
I don't necessarily understand the double brackets around [[var]]. Let me know if my answer does not correspond to what you were looking for!

We could use assign to create objects in the global env
for(i in 1:length(continent)){
var <- paste0("gdp_nsa_xdc_", continent[i])
var1 <- paste0(continent[i],"_iso2")
assign(var, imf_data(database_id = "IFS" , indicator = c("NGDP_NSA_XDC"),country =[[var1]],start = 2010, end = 2022,
return_raw = TRUE))
assign(var, get(var)$CompactData$DataSet$Series)
}

Related

how to make two networks connected with selected members

I have a data like this
df<- structure(list(Core = c("Bestman", "Tetra"), member1 = c("Tera1",
"Brownie1"), member2 = c("Tera2", "Brownie2"), member3 = c("Tera3",
"Brownie3"), member4 = c("Tera4", "Brownie4"), member5 = c("Tera5",
"Brownie5"), member6 = c("", "Brownie6"), member7 = c("", "Brownie7"
)), class = "data.frame", row.names = c(NA, -2L))
I want to connect all the members to their Core. for example if you look at the first row, you can see there are 5 members , I want to connect them to their Core
The same for the second row
Then I connect both Core together
Here is what I have done
mydf <- crossprod(table(cbind(df[1], stack(df[-1]))[-3]))
graph_from_adjacency_matrix(mydf, diag = F, weighted = T, mode = "undirected") %>%
plot(edge.width = E(.)$weight)
If i understood correctly, what you want is:
library(igraph)
df<- data.frame(Core = c("Bestman", "Tetra"), member1 = c("Tera1",
"Brownie1"), member2 = c("Tera2", "Brownie2"), member3 = c("Tera3",
"Brownie3"), member4 = c("Tera4", "Brownie4"), member5 = c("Tera5",
"Brownie5"), member6 = c("", "Brownie6"), member7 = c("", "Brownie7"))
edges <- t(do.call(rbind, apply(
df, 1, function(x) cbind(x[1], x[x!=""][-1]))))
core_edges <- if(nrow(df)>1) combn(df$Core,2) else c()
g<-graph(c(edges,core_edges), directed=F )
plot(g , edge.width = E(g)$weight)
EDIT
To colorize and resize nodes:
V(g)$color <- apply(df, 1, \(x) names(V(g)) %in% x) |> apply(1,which)
V(g)$size <- 15
V(g)[df$Core]$size <- degree(g, V(g)[df$Core]) + 15
plot(g)

In R--Change name of list of list of lists when lists have differing lengths

I've tried everything I can...I have a large list of lists. They are of varying depths, but they all have a variable name that I need to rename. I tried breaking apart the list into data frames, it just seems unpractical and doesn't even do what I want.
Here's a toy example:
list1 = list(changethis = c("1", "2"))
list2 = list(varname1 = c("1,2,3,4"), changethis = c("5,6,7,8"), varname2 = c("9, 10, 11"))
list3 = list(varname3 = list(varname4 = c("first", "second", "third", list(changethis = c("15, 16, 19"), varname5 = "cat", "dog", "fish"))))
list4 = list(varname6 = list(varname7 = list2, varname8 = list2))
list5a = list(varname13 = c("hat", "key"), changethis = c("5"))
list5 = list(varname9 = list(varname10 = list5a, varname11 = list5a))
list6 = list(varname12 = list5)
list7 = list(first = list1)
listbig = list(sublist1 = list3, sublist2 = list4, sublist3 = list5, sublist4= list6, sublist5=list7, sublist6 = list5a)
Here's a toy code that produces what I want it to look like. The 'changethis' var is renamed to 'change'
sollist1 = list(changed= c("1", "2"))
sollist2 = list(varname1 = c("1,2,3,4"), changed = c("5,6,7,8"), varname2 = c("9, 10, 11"))
sollist3 = list(varname3 = list(varname4 = c("first", "second", "third", list(changed = c("15, 16, 19"), varname5 = "cat", "dog", "fish"))))
sollist4 = list(varname6 = list(varname7 = sollist2, varname8 = sollist2))
sollist5a = list(varname13 = c("hat", "key"), changed = c("5"))
sollist5 = list(varname9 = list(varname10 = sollist7, varname11 = sollist5a))
sollist6 = list(varname12 = sollist5)
sollist7 = list(first = sollist1)
solution_list = list(sublist1 = sollist3, sublist2 = sollist4, sublist3 = sollist5, sublist4= sollist6, sublist5=sollist7, sublist6=sollist7)
Here is one of my many attempts to do this. I extracted sublist1 from the big list and tried to just change the name for it, but nothing gets changed.
extr_sublist1 <- listbig[1]
names(extr_sublist1[[1]][[1]][[1]][4]) <- "changed" #does not do it...
Another failed attempt:
In this I extract a differently hierarchial sublist and create a Var name which I hope to loop over so I can change the name of the 'changethis' var. Also does not work.
extr_sublist4 <- listbig[4]
numvars <- length(extr_sublist4[[1]][[1]][[1]])
for (i in 1: numvars){
varname<-paste("Var",numvar, sep = "")
paste('Var',[i]) <- extr_sublist4[[1]][[1]][[1]][[1]][2]
namespaste('Var',[i])[paste('Var',[i]) == 'changethis'] <- 'changed'
}
I'm sure there's a simple and elegant solution to this...but have no idea what. Thanks in advance for your help.
You can use a recursive method to do the transformation:
changefun <- function(x, change_name, new_name){
idx <- names(x) == change_name
if(any(idx)) names(x)[idx] <- new_name
if (is.list(x)) lapply(x, changefun, change_name, new_name)
else x
}
Now just call
changefun(listbig, 'changethis', 'changed')

Is it possible to make it more readable? treemap

I just wanna know how can I make it more readable.
marketcap <- data.frame(Marketcap = c(641899161594, 30552518424, 271028619181,
9277626785, 3986737880, 1202315485,
6049985280, 30722840711),
id = c('Bitcoin', 'Dogecoin', 'Ethereum', 'Litecoin', 'Monero', 'Nem', 'Stellar', 'xrp'),
row.names = c('Bitcoin', 'Dogecoin', 'Ethereum', 'Litecoin', 'Monero', 'Nem',
'Stellar', 'xrp')); df
#install.packages('treemap')
library(treemap)
df1 <- na.omit(marketcap[,c('id','Marketcap')])
df1$Marketcap <- as.numeric(round(df1$Marketcap, 0))
df1$formatted_market_cap = paste0(df1$id, '\n', '$', formatC(c("642","30.5","271","9.3","4","1.2","6.044","30.7"), format = "e", digits = 2))
treemap(df1, index = 'formatted_market_cap', vSize = 'Marketcap', title = 'Cryptocurrency Market Cap (bn)', fontsize.labels=c(15, 4), palette='Set3')
For example, Nem is looking poor

Create a script with 2 vectors in R

I'm using Heatmap from the package complexheatmap
in the script, I need to create a variable ha_column that I will incorporate into my script.
ha_column = HeatmapAnnotation (df = data.frame(type1=c(rep("name1",5), rep("name2",5),rep("name3",5), col = list(type1=c("name1" = "#DCDCDC", "name2" = "#DC928B", "name2"="#BA72D3")))))
I have 2 vectors:
vectors1=c("name1","name2","name3)
vectors2=c("#DCDCDC","#DC928B","#BA72D3")
and the idea is to reproduce the above script with these two vectors.
I tried:
paste0("ha_column = HeatmapAnnotation(df = data.frame(type1 = c(rep(",vectors1,", 5),col = list(type1 = c(",vectors1,"=",vectors2,")))")
bu it only paste line by line such as:
[1] "ha_column = HeatmapAnnotation(df = data.frame(type1 = c(rep(name1, 5),col = list(type1 = c(name1=#DCDCDC)))"
[2] "ha_column = HeatmapAnnotation(df = data.frame(type1 = c(rep(name2, 5),col = list(type1 = c(name2=#DC928B)))"
[3] "ha_column = HeatmapAnnotation(df = data.frame(type1 = c(rep(name3, 5),col = list(type1 = c(name3=#BA72D3)))"
instead of doing what I want ...
Does anyone have an idea?
Thanks for your time.
It's generally not a good idea to build code as a string. Instead think of building a function to do what you want.
You could do something line
ha_column_fun = function(names, colors) {
HeatmapAnnotation(
df = data.frame(type1 = rep(names, each=5)),
col = list(type1=setNames(colors, names))
)
}
And then you could call it with
ha_column = ha_column_fun(vectors1, vectors2)

Create argument list using lapply for do.call

I'm trying to pass a set of modified arguments from a larger function to arguments in a nested function. This is an argument supplied from the larger function:
time_dep_covariates_list = c(therapy_start = "Start of Therapy",
therapy_end = "End of Therapy")
I have these sets of constant arguments:
tmerge_args_1 <- alist(data1 = analytic_dataset,
data2 = analytic_dataset,
id = patientid,
tstop = adv_dx_to_event,
death_censor = event(adv_dx_to_event))
And I want to append these modified arguments to that argument list:
tmerge_args_2 <- lapply(1:length(time_dep_covariates_list), function(x){
tmerge_args <<- c(tmerge_args, alist('var' = tdc(var)) )
paste0(names(time_dep_covariates_list[x])," =
tdc(",names(time_dep_covariates_list[x]), ")")
})
> tdc_args
[[1]]
[1] "therapy_start = tdc(therapy_start)"
[[2]]
[1] "therapy_end = tdc(therapy_end)"
I want to create a do.call that handles the arguments like so:
count_process_form <- do.call(tmerge, args = c(tmerge_args_1,
tmerge_args_2)
That would be identical to the following:
tmerge(data1 = analytic_dataset, data2 = analytic_dataset,
id = patientid, tstop = adv_dx_to_event,
therapy_start = tdc(therapy_start), therapy_end = tdc(therapy_end)
It works fine with tmerge_args_1 by itself, but as the args_2 are character and not language elements, I get this error:
Error in (function (data1, data2, id, ..., tstart, tstop, options) :
all additional argments [sic] must have a name:
How can I modify the list I'm creating for args_2 so they're stored as arguments that do.call can understand? Or am I approaching this all wrong?
Thanks!
Here is a reproducible example:
analytic_dataset= data_frame(patientid = sample(1:1000,5),
adv_dx_to_event = sample(100:200, 5),
death_censor = sample(0:1,5, replace = T),
therapy_start = sample(1:20,5),
therapy_stop = sample(40:100,5))
The below would be passed in from a function:
time_dep_covariates_list = c(therapy_start = "Start of Therapy",
therapy_end = "End of Therapy")
tmerge_args_1 <- alist(data1 = analytic_dataset,
data2 = analytic_dataset,
id = patientid,
tstop = adv_dx_to_event,
death_censor = event(adv_dx_to_event))
do.call(tmerge,tmerge_args_1) #this works
tmerge_args_2 <- lapply(1:length(time_dep_covariates_list), function(x){
tmerge_args <<- c(tmerge_args, alist('var' = tdc(var)) )
paste0(names(time_dep_covariates_list[x])," = tdc(",names(time_dep_covariates_list[x]), ")")
})
do.call(tmerge,tmerge_args_1,tmerge_args_2) # this doesn't```

Resources