I need to create as many copies of the same df with as names of those data-frames changing values stored in a vector.
For example:
z <- c("A-1", "B-2", "C-2", ...)
for (i in z) {
i <- already_existing_df
}
Manual hard-coding would be something like:
`A-1` <- df
`B-2` <- df
# ...and so on
Of course I would want to automate this, and not hardcode it... also 'cause it will change every month, and we are talking about many dfs...
Now, I know that to pass i as a variable name, you can simply do:
df[i]
but I don't know how to pass i as a df name.
Thank you in advance for any help!
Another approach could be using replicate to repeat the dataframe length(z) times and assign the names to the list
z <- c("A-1", "B-2", "C-2")
list_df <- setNames(replicate(length(z), df, simplify = FALSE), z)
You can then keep list of dataframes as it is or make them as separate dataframe.
list2env(list_df, .GlobalEnv)
Depending on your desired result you could define a list (or an Environment):
z <- vector("list", 3)
for (i in seq_along(z)) {
z[[i]] <- already_existing_df
}
names(z) <- c("A-1", "B-2", "C-2")
You can do assign(df, z) which will assign df to your enviroment under the i element of z.
Related
I have a problem which I am sure has an easy answer, but I seem to be unable to figure it out. I have many matrices of the same format, and would like to assign the same column and row names to all of them. I am trying to do this in a loop, by calling all the matrices and then to assign the names.
Here is my reproducible example.
mnames <- letters[1:10] # The names to be assigned
mat1 <- matrix(rnorm(100),10,10)
mat2 <- matrix(rnorm(100),10,10)
mat3 <- matrix(rnorm(100),10,10)
obs <- c("mat2", "mat2", "mat3")
for(i in obs){
rownames(as.name(i)) <- mnames
colnames(as.name(i)) <- mnames
}
It seems like the loop does not call the object, but I do not understand why? Would be grateful for any help, I have tons of matrices and doing all the assigning one by one would be tedious. Thanks!
You can get the matrix in for loop but I think it would be better if you get them in a list with mget, change the dimnames and then if needed assign it back to global enviroment.
list_mat <- lapply(mget(obs), function(x) {dimnames(x) <- list(mnames, mnames);x})
list2env(list_mat, .GlobalEnv)
I'm making a function and I'd like to call a column in a particular way.
Initialize data
a <- c(1,2,3,4,5)
b <- c(6,7,8,9,10)
c <- c(1,2,3,4,5)
d <- c(6,7,8,9,10)
df <- as.data.frame(cbind(a,b,c,d))
Call column for the table function
Func <- function(df){
X <- df
Y <- names(M)
for(i in 1:2){
table(X$___,X$___)
}}
The trouble is I don't know how to call the columns.
I'd like it to be the equivalent to table(X$a, X$b) as it iterates through the loop.
I tried this and it didn't work
for(i in 1:2){
Q <- Y[i]
W <- Y[j]
table(X$Q,X$W)
}}
It is necessary for a function I'm using that I make a table with the form table(X$a, X$b) and I don't know quite how to achieve that in a for loop?
Instead of calling table using names of the column you could use column index and use it in the function so you don't have to worry about how to call the columns.
Replace your for loop and use
table(df[1:2])
which would give you the expected result.
You need to use two [[ to get the content of the column:
df <- datasets::mtcars
for (i in 1:2) df[[i]]
This will also work for column names
for (i in names(df)) df[[i]]
Not sure what you are trying to achieve though. You can also just do:
lapply(df[1:2], table)
You can also loop through col using column index. In the following code you can loop through iris dataset column:
for(i in 1:length(colnames(iris))){
print(iris[,i]) # to get single column
print(iris[,c(i,i+1)]) # to get multiple column data
}
How can I append/ push data into union dynamically?
For instance, I have 4 data sets to merge,
mydata <- union(data1, data2, data3, data4)
But sometimes I have less than 4 while sometimes more than that.
Any ideas how can I solve this problem?
Make some reproducible data:
#dummy data
data1 <- data.frame(x=letters[1:3])
data2 <- data.frame(x=letters[2:4])
data3 <- data.frame(x=letters[5:7])
We can use rbind with unique in a string then evaluate:
#get list of data frames to merge, update pattern as needed
data_names <- ls()[grepl("data\\d",ls())]
data_names <- paste(data_names,collapse=",")
#make command string
myUnion <- paste0("unique(rbind(",data_names,"))")
#evaluate
eval(parse(text=myUnion))
EDIT:
Here is another better/simpler way, using do.call:
unique(do.call("rbind",lapply(objects(pattern="data\\d"),get)))
You could roll your own function like vunion defined below. Not sure if this actually works, my [R] got a bit stale ;)
Basically, you accept any number of arguments (hence ...) and make use of those as if they were packed in a list. Just choose and remove the first 2 items from that list, calculate their union, append them to the list, repeat.
vunion <- function(...){
data <- list(...)
n <- length(data)
if(n > 2){
u <- list(t(union(data[[1]], data[[2]])))
return(do.call(vunion, as.list(c(tail(data, -2), u))))
} else {
return(union(data[[1]], data[[2]]))
}
}
It sounds simple, but I have many problems trying to convert a List to Data Frame.
I did it with the as.data.frame function and it works, but when I use the str function the internal structure still remains with the List structure. And I would like to select a specific column to work in it.
There is some easy way to convert a List to Data Frame, but with a new data frame structure?
I have tryied also unlisting my List into a matrix but I lose the colnames and rownames, and I have to put it again manually.
For example that is my List, and I would like to use and plot the mystats$p.value column:
library(gtools)
x <- rnorm(100, sd=1)
y <- rnorm(100, sd =2)
mystats <- t(running(x, y, fun = cor.test, width=5, by=5))
Thanks
If and only if it's a list of data.frames you can use do.call
al <- split(airquality, airquality$Month)
sapply(al, class)
same.airquality <- do.call(rbind, al)
Here the list elements have the same structure of columns (for list that "splits" different variables across list elements, each the same nrow), you can use
do.call(cbind, another.list)
Finally (but not tested) with this approach you could try package abind
EDIT
After the example provided i understand a little more your setting: you shoud sanitize a bit the call to cor.test because with running it messes data a bit (currently you are trying to put a list, a complex data structure, in a matrix like object)
foobar <- function(x,y) {
my.test <- cor.test(x,y)
## look at values returned by names(cor.test) or ?cor.test for
## which object you can export
c(my.test$statistic, my.test$p.value, my.test$conf.int)
}
## mystats is a matrix
mystats <- as.data.frame(t(running(x, y, fun = foobar, width=5, by=5)))
names(mystats) <- c("statistic", "p.value", "low.ci", "up.ci")
mystats$p.value
If you have multiple objects like this one, eg
mystats$row <- row.names(mystats)
mystats$rep <- 1
row.names(mystats) <- NULL
mystats2 <- mystats
mystats2$rep <- 2
asd <- list(mystats, mystats2)
foo <- do.call("rbind", asd )
foo
foo$p.value
HTH
I have multiple data frames named y1 to y13 - one column each. They all have a column name that I would like to change to "Date.Code". I've tried the following in a for loop:
for(i in 1:13){
colnames(get(paste("y", i, sep=""))) <- c("Date.Code")
}
That didn't work.
I also tried:
for(i in 1:13){
assign(("Date.Code"), colnames(get(paste("y", i, sep=""))))
}
Also with no luck.
Any suggestions?
Thanks,
E
The difficulty here is that you cannot use get with an assignment operator directly
eg, get(nm) <- value will not work. You can use assign, as you're trying, but in a slightly different fashion.
assuming cn is the column number whose name you would like to change
for(i in 1:13){
nm <- paste0("y", i)
tmp <- get(nm)
colnames(tmp)[cn] <- c("Date.Code")
assign(nm, tmp)
}
That being said, a cleaner way of approaching this would be to collect all of your DF's into a single list, then you can easily use lapply to operate on them. For Example:
# collect all of your data.frames into a single list.
df.list <- lapply(seq(13), function(i) get(paste0("y", i)))
# now you can easily change column names. Note the `x` at the end of the function which serves
# as a return of the value. It then gets assigned back to an object `df.list`
df.list <-
lapply(df.list, function(x) {colnames(x)[cn] <- "Date.Code"; x})
Lastly, search these boards for [r] data.table and you will see many options for changing values by reference and setting attributes more directly.
Here one liner solution:
list2env(lapply(mget(ls(pattern='y[0-9]+')),
function(x) setNames(x,"Date.Code")),.GlobalEnv)
Of course it is better to keep all your variable in the same list.