Using Variable Value as Column Name in Data.Frame or Cbind

cbind a dynamic column name from a string in R

We can use tidyverse to do this

library(dplyr)
test_data %>%
mutate(!! y_attribute := NA)
# col1 Survived
#1 1 NA
#2 2 NA
#3 3 NA
#4 4 NA
#5 5 NA

data

test_data <- data.frame(col1 = 1:5)

How to name a column using cbind, in a loop

A simple solution will be to set the colname in the loop like:

df_final <- NULL
for (i in colnames(df)){
df_final <- cbind(df_final, df[,i])
colnames(df_final)[ncol(df_final)] <- i
}
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
# num [1:51, 1:3] 0 1 2 3 4 5 6 7 8 9 ...
# - attr(*, "dimnames")=List of 2
# ..$ : NULL
# ..$ : chr [1:3] "x" "y" "z"

For using the method x[[i]] <- value, x need to have rows:

df_final <- data.frame()[seq_len(nrow(df)),0] #Create empty data frame with rows
for (i in colnames(df)){
df_final[[i]] <- df[,i]
}
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
#'data.frame': 51 obs. of 3 variables:
# $ x: num 0 1 2 3 4 5 6 7 8 9 ...
# $ y: num 50 51 52 53 54 55 56 57 58 59 ...
# $ z: num 25 26 27 28 29 30 31 32 33 34 ...

otherwise it will create a list:

df_final <- NULL
for (i in colnames(df)){
df_final[[i]] <- df[,i]
}
colnames(df_final)
#NULL
str(df_final)
#List of 3
# $ x: num [1:51] 0 1 2 3 4 5 6 7 8 9 ...
# $ y: num [1:51] 50 51 52 53 54 55 56 57 58 59 ...
# $ z: num [1:51] 25 26 27 28 29 30 31 32 33 34 ...

df_final <- do.call("cbind", df_final)
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
# num [1:51, 1:3] 0 1 2 3 4 5 6 7 8 9 ...
# - attr(*, "dimnames")=List of 2
# ..$ : NULL
# ..$ : chr [1:3] "x" "y" "z"

When the loop is done with sapply instead of for a solution would be:

df_final <- sapply(colnames(df), function(i) {df[,i]})
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
# num [1:51, 1:3] 0 1 2 3 4 5 6 7 8 9 ...
# - attr(*, "dimnames")=List of 2
# ..$ : NULL
# ..$ : chr [1:3] "x" "y" "z"

Or simply subsetting:

df_final <- df[colnames(df)]
colnames(df_final)
#[1] "x" "y" "z"
str(df_final)
#'data.frame': 51 obs. of 3 variables:
# $ x: num 0 1 2 3 4 5 6 7 8 9 ...
# $ y: num 50 51 52 53 54 55 56 57 58 59 ...
# $ z: num 25 26 27 28 29 30 31 32 33 34 ...

How to cbind the column by same value with id but reserve the variable by different length

One way is to match both columns, i.e.

A$year.y <- A$year[match(do.call(paste0, A), do.call(paste0, B))]

ID year year.y
1 1 2000 2000
2 1 2001 2001
3 1 2002 2002
4 2 2000 NA
5 2 2001 2000
6 2 2002 2001
7 3 2000 NA
8 3 2001 NA
9 3 2002 2002

What is the difference in cbind when used with index compared with variable name

This is because of the class of the object that is being called. It has nothing to do with cbind().

When a column is chosen from a data frame using the column number, the chosen column is extracted as data frame. If a single column is called, the extracted object will be a data frame with one column. If more than one column are called, then the extracted object will be the data frame with columns as many as called.

When a column is chose using the column name, the chosen column is extracted as vector with no name. If a single column is called, the extracted object will be a a single vector. If more than one column are called, then the extracted object will be a vector of vectors as many as called.

If you run the str(), you could find the difference.

> str(iris[1])
'data.frame': 150 obs. of 1 variable:
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...

> str(iris$Sepal.Length)
num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...

You could see that the class of the former is data.frame consisting of a numeric vector and that of the latter is numeric.

Assign the results of do.call using cbind to data frames

I've figured out a way to do it. A few notes: I have 360 data sets that I need to combine, which is why it is i in 1:360. This also names the data sets from an array of the names of the data sets (which is dataNames)

for (i in 1:360){
assign(paste(dataNames[i], sep = ""), cbind(names[[i]], namesLPC[[i]]))
}


Related Topics



Leave a reply



Submit