I am trying to create a list out of the result from a for loop in R.
Then I want to use cbind to add the list into the dataframe.
When I run this code, it does not work.
Can you please help?
GenSpc <- list()
for(i in 1:68) {
paste(NewtableAllLoci$host_genus[i], NewtableAllLoci$host_species[i], collapse = " ")
}
You do not assigned anything to the target list GenSpc. To get want you want, do:
GenSpc <- rep(0, nrow(NewtableAllLoci))
for(i in 1:nrow(NewtableAllLoci)) {
GenSpc[i] <- paste(NewtableAllLoci$host_genus[i], NewtableAllLoci$host_species[i], collapse = " ")
}
D <- cbind(NewtableAllLoci, GenSpc)
Related
I want to get those tables with same name added numbers by combining two columns from different tables (only one column in each table).
part of code is like this( I don't know how many tables in advance. So I have to use n input by users)
for(i in 1: n)
{
data[i]<-data.frame(X=X[i],Y=Y[i])
}
I want to get like
data1 is (X1,Y1)
data2 is (X2,Y2)
.... is ....
In addition. after create those tables data1,data2...
then how to use a general expression to print them one by one?
I know it does not work. But How to do it ?
Try this:
data_list <- list()
for(i in 1: n) {
data_list[[i]] <- data.frame(X = X[i], Y = Y[i])
}
## alternately, if `X` and `Y` are data frames
data_list <- split(cbind(X, Y), 1:n)
Printing is easier if we don't put things in separate data frames:
print(paste0("data", 1:n, " is (", X[[1]], ", ", Y[[1]], ")"))
But you can still do it:
for(i in 1:n) {
print(paste0("data", i, " is (", data_list[[i]]$X, ", ", data_list[[i]]$Y, ")"))
}
I discovered that it seems that I can not add rows to a data.frame in place.
The following code is a minimal example which should append a new row to the data.frame every iteration, but it does not append any.
Please note, in reality I have a complex for-loop with a lot of different if-statements and depending on them I want to append new different data to different data frames.
df <- data.frame(value=numeric())
appendRows <- function(n_rows) {
for(i in 1:n_rows) {
print(i)
df <- rbind(df, setNames(i,names(df)))
}
}
appendRows(10) #Does not append any row, whereas "df <- rbind(df, setNames(1,names(df)))" in a single call appends one row.
How can rows be added to a data.frame in place?
Thanks :-)
Don't forget to return your object:
df <- data.frame(value=numeric())
appendRows <- function(n_rows) {
for(i in 1:n_rows) {
print(i)
df <- rbind(df, setNames(i,names(df)))
}
return(df)
}
appendRows(10)
To modify df you have to store it:
df <- appendRows(10)
So I am trying to make a basic sensitivity analysis script. The outputs come out as I want via the print I added to the end of the script. Issue is that I would like a tibble or object that has all the outputs appended together that I can export as a csv or xlsx.
I created two functions, sens_analysis which runs all the code, and multiply_across which multiplies across each possible percentage across each possible column of your table. You need multiply_across to run the sens_analysis.
I would normally like a title but instead I just added an indicator column instead that I can sort by.
I made everything with mtcars so it should be easy to replicate, the issue is that I just have a huge print at the end; not an object that I can manipulate or pull from for other analysis.
I have been trying the rbind, bind_row, appending rows in a variety of ways.
Or building a new object. As you can see in the code at line (18) I make something called output that I have tried to populate, which hasn't gone well.
rm(list = ls())
library(dplyr)
library(tidyr)
library(purrr)
library(tibble)
library(magrittr)
library(xtable)
data<-mtcars
percent<-c(.05,.1,.15)
goods<-c("hp","gear","wt")
weight<-c(6,7,8)
disagg<-"cyl"
func<-median
sens_analysis<-function(data=data, goods=goods, weight=weight, disagg=disagg, precent=percent, func=func){
output<-NULL%>%
as.tibble()
basket<-(rbind(goods,weight))
percent<-c(0,percent,(percent*-1))
percent_to_1<-percent+1
data_select<-data%>%
dplyr::select(c(goods,disagg))%>%
group_by_at(disagg)%>%
summarise_at(.vars = goods ,.funs = func)%>%
as_tibble()
data_select_weight<-purrr::map2(data_select[,-1], as.numeric(basket[2,]),function(var, weight){
var*weight
})%>% as_tibble %>%
add_column(data_select[,1], .before = 1)
colnames(data_select_weight)[1]<-disagg
multiply_across(data_select_weight,percent_to_1)
return(output)
#output2<-rbind(output2,output)
}
############################
multiply_across<-function(data=data_select_weight,list=percent_to_1){
varlist<-names(data[,-1])
for(i in varlist){
df1 = data[,i]
for(j in list){
df<-data
df[,i]<-round(df1*j,2)
df<-mutate(df, total = round(rowSums(df[,-1]),2))%>%
mutate(type=paste0(i," BY ",(as.numeric(j)-1)*100,"% OVER ",disagg))%>%
print(df)
#output<-bind_rows(output,df)
#output<-bind_rows(output,df)
#output[[j]]<-df[[j]]
}
}
}
##############################################################################################
sens_analysis(data,goods,weight,disagg,percent,func)
The expected result if you just run the code straight-up should just be a bunch of printed tibbles, that arent in an object. But ideally, for future analysis on the data or easy of use, a table of the outputs appended together would be best.
So I figured it out and will add my answer here in case someone else hits this issues.
I created a list within loops and then binded those lists together.
Just focus on the binding rows outside the right for-loop.
multiply_across<-function(data=data_select_weight,
list=percent_to_1){
varlist <- colnames(data[, -1])
output_list <- list()
for (i in varlist) {
df1 <- data[,i]
for (j in list) {
name <- paste0(i, " BY ", (as.numeric(j)-1)*100, "% OVER ", disagg)
df <- as_tibble(data)
df[,i] <- round(df1*j, 2)
df <- mutate(df, total = round(rowSums(df[,-1]),2))%>%
mutate(type = paste0(i, " BY ", (as.numeric(j)-1)*100, "% OVER ", disagg))
df<-df[,c(6,1,2,3,4,5)]
output_list[[paste0(i," BY ",(as.numeric(j)-1)*100)]] <- (assign(paste0(i," BY ",(as.numeric(j)-1)*100,"% OVER ",disagg),df))
}
}
bind_rows(lapply(output_list,
as.data.frame.list,
stringsAsFactors=F))
}
please help a newbie here. I want to extract the TOTAL_SITE information from the sites1 data frame. The data frame looks like:
FACILITY TOTAL_SITE
A 100
B 80
C 20
if(nrow(sites1) > 0){
outStr <- "<ul>"
for(site in sites1$FACILITY){
outStr <- paste0(outStr,"<li>",site,": ", sites1$TOTAL_SITE, "</li>")
}
outStr <- paste0(outStr, "</ul>")
} else {
outStr <- ""
}
However, the result shows repeatedly printing lines and indicates that I shouldn't loop through sites1$FACILITY and sites1$TOTAL_SITE concurrently. How can I use the index (row number) that will be corresponding to both columns of the sites1 data frame?
This will get the TOTAL_SITE data from the df (not sure if this is what you mean?)
TotalSiteData<-sites1["TOTAL_SITE"]
But this should keep corresponding row numbers and the data you're after.
If I understood correctly, you need to make an HTML unordered list from TOTAL_SITE column, correct? Hopefully this solves your problem:
total_site <- sites1[,"TOTAL_SITE"]
outStr <- sapply(total_site, function(value){
paste("<li>", value, "</li>", sep = "")
})
outStr <- paste("<ul>", outStr, "</ul>")
I believe this is what you are asking for:
if(nrow(sites1) > 0)
outStr <- paste0("<ul>",
paste0("<li>", sites1$FACILITY, ": ", sites1$TOTAL_SITE, "</li>",collapse=""),
"</ul>"
)
else
outStr <- ""
This code will take your data.frame's columns and paste them together by rows, assigning outStr the following character vector in your example:
<ul><li>A: 100</li><li>B: 80</li><li>C: 20</li></ul>
I'm attempting to create a loop in R that will use a vector of dates, run them through a loop that includes a SQL query, and then generate a separate dataframe for each output. Here is as far as I've gotten:
library(RODBC)
dvect <- as.Date("2015-04-13") + 0:2
d <- list()
for(i in list(dvect)){
queryData <- sqlQuery(myconn, paste("SELECT
WQ_hour,
sum(calls) as calls
FROM database
WHERE DDATE = '", i,"'
GROUP BY 1
", sep = ""))
d[i] <- rbind(d, queryData)
}
From what I can tell, the query portion of the code runs fine since I've tested it by itself. Where I'm stumbling is the last line where I try to save the contents of each loop through the query separately with each having a label of the date that was used in the loop.
I'd appreciate any help. I've only been using R consistently for about 2 months now so I'm definitely open to alternative ways of doing this that are cleaner and more efficient.
Thanks.
I'd suggest making the SQL query a function, and use lapply to apply it and return your result as a list.
userSQLquery = function(i) {
sqlQuery(myconn, paste("SELECT
WQ_hour,
sum(calls) as calls
FROM database
WHERE DDATE = '", i,"'
GROUP BY 1
", sep = ""))
}
dvect = as.Date("2015-04-13") + 0:2
d = as.list(1:length(dvect))
names(d) = dvect
lapply(d, userSQLquery)
I have very little experience with SQL though, so this may not work. Maybe it could start you off?
Looks like a job for lapply (lapply documentation)instead of a for loop. (In R it's often good to avoid a for loop by using a vectorization.)
If you want each date to return a separate data frame, and then have each data frame labelled with the original date, try:
dates <- c("Jan 1", "Oct 31", "Dec 25")
queryData <- function(date){
#dummy data
return(runif(5))
}
results <- lapply(dates, queryData)
names(results) <- dates
Either use:
d[[i]] <- queryData
if you want each data.frame (query result) as a separate element in the list output d.
Or use:
d <- rbind(d, queryData)
if you want a single data.frame with all the query outputs combined. In this case you should declare d as a data.frame (i.e. d <- data.frame()).
You can also store each data.frame (i.e. the query result) with its corresponding date in a list as:
d[[i]] <- list(date = dvect[[i]], queryResult = queryData)
I think the last one is what you are looking for.