I have a data frame that has columns a, b, and c. I\'d like to add a new column d between b and c.
I know I could just add d at the end by using cbind but h
R has no functionality to specify where a new column is added. E.g., mtcars$mycol<-'foo'
. It always is added as last column. Using other means (e.g., dplyr's select()
) you can move the mycol to a desired position. This is not ideal and R may want to try to change that in the future.
I would suggest you to use the function add_column()
from the tibble package.
library(tibble)
dataset <- data.frame(a = 1:5, b = 2:6, c=3:7)
add_column(dataset, d = 4:8, .after = 2)
Note that you can use column names instead of column index :
add_column(dataset, d = 4:8, .after = "b")
Or use argument .before
instead of .after
if more convenient.
add_column(dataset, d = 4:8, .before = "c")
This function inserts one zero column between all pre-existent columns in a data frame.
insertaCols<-function(dad){
nueva<-as.data.frame(matrix(rep(0,nrow(daf)*ncol(daf)*2 ),ncol=ncol(daf)*2))
for(k in 1:ncol(daf)){
nueva[,(k*2)-1]=daf[,k]
colnames(nueva)[(k*2)-1]=colnames(daf)[k]
}
return(nueva)
}
You can use the append()
function to insert items into vectors or lists (dataframes are lists). Simply:
df <- data.frame(a=c(1,2), b=c(3,4), c=c(5,6))
df <- as.data.frame(append(df, list(d=df$b+df$c), after=2))
Or, if you want to specify the position by name use which
:
df <- as.data.frame(append(df, list(d=df$b+df$c), after=which(names(df)=="b")))
`
data1 <- data.frame(col1=1:4, col2=5:8, col3=9:12)
row.names(data1) <- c("row1","row2","row3","row4")
data1
data2 <- data.frame(col1=21:24, col2=25:28, col3=29:32)
row.names(data2) <- c("row1","row2","row3","row4")
data2
insertPosition = 2
leftBlock <- unlist(data1[,1:(insertPosition-1)])
insertBlock <- unlist(data2[,1:length(data2[1,])])
rightBlock <- unlist(data1[,insertPosition:length(data1[1,])])
newData <- matrix(c(leftBlock, insertBlock, rightBlock), nrow=length(data1[,1]), byrow=FALSE)
newData
`
When you can not assume that column b
comes before c
you can use match
to find the column number of both, min
to get the lower column number and seq_len
to get a sequence until this column. Then you can use this index first as a positive subset, than place the new column d
and then use the sequence again as a negative subset.
i <- seq_len(min(match(c("b", "c"), colnames(x))))
data.frame(x[i], d, x[-i])
#cbind(x[i], d, x[-i]) #Alternative
# a b d c
#1 1 4 10 7
#2 2 5 11 8
#3 3 6 12 9
In case you know that column b
comes before c
you can place the new column d
after b
:
i <- seq_len(match("b", colnames(x)))
data.frame(x[i], d, x[-i])
# a b d c
#1 1 4 10 7
#2 2 5 11 8
#3 3 6 12 9
Data:
x <- data.frame(a = 1:3, b = 4:6, c = 7:9)
d <- 10:12