在data.frame中的两列之间添加一列

时间:2021-12-04 19:35:59

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 how can I insert it in between two columns?

我有一个数据框架,它有a、b和c列,我想在b和c之间添加一个新的d列,我知道我可以用cbind来添加d但是我怎么能把它插入到两列之间呢?

13 个解决方案

#1


33  

I would suggest you to use the function add_column() from the tibble package.

我建议您使用tibble包中的函数add_column()。

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.

或者使用参数。before而不是。after if更方便。

add_column(dataset, d = 4:8, .before = "c")

#2


26  

Just an R beginner, but I think this also works:

只是一个初学者,但我认为这也可以:

Add in your new column:

加入你的新专栏:

df$d <- list/data

Then you can reorder them.

然后你可以重新排序。

df <- df[,c("a","b","d","c")]

#3


19  

You can reorder the columns with [, or present the columns in the order that you want.

可以使用[对列进行重新排序,或者按所需的顺序显示列。

d <- data.frame(a=1:4, b=5:8, c=9:12)
target <- which(names(d) == 'b')[1]
cbind(d[,1:target,drop=F], data.frame(d=12:15), d[,(target+1):length(d),drop=F])

  a b  d  c
1 1 5 12  9
2 2 6 13 10
3 3 7 14 11
4 4 8 15 12

#4


10  

Presuming that c always immediately follows b, this code will add a column after b no matter where b is in your data.frame.

假设c总是紧跟着b,不管b在你的data.frame中的什么位置,这段代码都会在b之后添加一列。

> test <- data.frame(a=1,b=1,c=1)
> test
  a b c
1 1 1 1

> bspot <- which(names(test)=="b")

> data.frame(test[1:bspot],d=2,test[(bspot+1):ncol(test)])
  a b d c
1 1 1 2 1

Or possibly more naturally:

或者可能更自然:

data.frame(append(test, list(d=2), after=match("b", names(test))))

#5


4  

Create an example data.frame and add a column to it.

创建一个示例data.frame并向其添加一个列。

df = data.frame(a = seq(1, 3), b = seq(4,6), c = seq(7,9))
df['d'] <- seq(10,12)
df

  a b c  d
1 1 4 7 10
2 2 5 8 11
3 3 6 9 12

Rearrange by column index

重新排列的列索引

df[, colnames(df)[c(1:2,4,3)]]

or by column name

或列名

df[, c('a', 'b', 'd', 'c')]

The result is

结果是

  a b  d c
1 1 4 10 7
2 2 5 11 8
3 3 6 12 9

#6


3  

You would like to add column z to the old data frame (old.df) defined by columns x and y.

您希望将列z添加到由列x和y定义的旧数据帧(old.df)。

z = rbinom(1000, 5, 0.25)
old.df <- data.frame(x = c(1:1000), y = rnorm(1:1000))
head(old.df)

Define a new data frame called new.df

定义一个名为new.df的新数据帧

new.df <- data.frame(x = old.df[,1], z, y = old.df[,2])
head(new.df)

#7


2  

For what it's worth, I wrote a function to do this:

为了它的价值,我写了一个函数来做这个:

[removed]

(删除)


I have now updated this function with before and after functionality and defaulting place to 1. It also has data table compatability:

我现在已经更新了这个函数,之前和之后的功能和默认位置都是1。它也有数据表的兼容性:

#####
# FUNCTION: InsertDFCol(colName, colData, data, place = 1, before, after)
# DESCRIPTION: Takes in a data, a vector of data, a name for that vector and a place to insert this vector into
# the data frame as a new column. If you put place = 3, the new column will be in the 3rd position and push the current
# 3rd column up one (and each subsuquent column up one). All arguments must be set. Adding a before and after
# argument that will allow the user to say where to add the new column, before or after a particular column.
# Please note that if before or after is input, it WILL override the place argument if place is given as well. Also, place
# defaults to adding the new column to the front.
#####

InsertDFCol <- function(colName, colData, data, place = 1, before, after) {

  # A check on the place argument.
  if (length(names(data)) < place) stop("The place argument exceeds the number of columns in the data for the InsertDFCol function. Please check your place number")
  if (place <= 0 & (!missing(before) | !(missing(after)))) stop("You cannot put a column into the 0th or less than 0th position. Check your place argument.")
  if (place %% 1 != 0 & (!missing(before) | !(missing(after)))) stop("Your place value was not an integer.")
  if (!(missing(before)) & !missing(after)) stop("You cannot designate a before AND an after argument in the same function call. Please use only one or the other.")

  # Data Table compatability.
  dClass <- class(data)
  data <- as.data.frame(data)

  # Creating booleans to define whether before or after is given.
  useBefore <- !missing(before)
  useAfter <- !missing(after)

  # If either of these are true, then we are using the before or after argument, run the following code.
  if (useBefore | useAfter) {

    # Checking the before/after argument if given. Also adding regular expressions.
    if (useBefore) { CheckChoice(before, names(data)) ; before <- paste0("^", before, "$") }
    if (useAfter) { CheckChoice(after, names(data)) ; after <- paste0("^", after, "$") }

    # If before or after is given, replace "place" with the appropriate number.
    if (useBefore) { newPlace <- grep(before, names(data)) ; if (length(newPlace) > 1) { stop("Your before argument matched with more than one column name. Do you have duplicate column names?!") }}
    if (useAfter) { newPlace <- grep(after, names(data)) ; if (length(newPlace) > 1) { stop("Your after argument matched with more than one column name. Do you have duplicate column names?!") }}
    if (useBefore) place <- newPlace # Overriding place.
    if (useAfter) place <- newPlace + 1 # Overriding place.

  }

  # Making the new column.
  data[, colName] <- colData

  # Finding out how to reorder this.
  # The if statement handles the case where place = 1.
  currentPlace <- length(names(data)) # Getting the place of our data (which should have been just added at the end).
  if (place == 1) {

    colOrder <- c(currentPlace, 1:(currentPlace - 1))

  } else if (place == currentPlace) { # If the place to add the new data was just at the end of the data. Which is stupid...but we'll add support anyway.

    colOrder <- 1:currentPlace

  } else { # Every other case.

    firstHalf <- 1:(place - 1) # Finding the first half on columns that come before the insertion.
    secondHalf <- place:(currentPlace - 1) # Getting the second half, which comes after the insertion.
    colOrder <- c(firstHalf, currentPlace, secondHalf) # Putting that order together.

  }

  # Reordering the data.
  data <- subset(data, select = colOrder)

  # Data Table compatability.
  if (dClass[1] == "data.table") data <- as.data.table(data)

  # Returning.
  return(data)

}

I realized I also did not include CheckChoice:

我意识到我也没有包括CheckChoice:

#####
# FUNCTION: CheckChoice(names, dataNames, firstWord == "Oops" message = TRUE)                                                                                               
# DESCRIPTION: Takes the column names of a data frame and checks to make sure whatever "choice" you made (be it 
# your choice of dummies or your choice of chops) is actually in the data frame columns. Makes troubleshooting easier. 
# This function is also important in prechecking names to make sure the formula ends up being right. Use it after 
# adding in new data to check the "choose" options. Set firstWord to the first word you want said before an exclamation point.
# The warn argument (previously message) can be set to TRUE if you only want to 
#####

CheckChoice <- function(names, dataNames, firstWord = "Oops", warn = FALSE) {

  for (name in names) {

    if (warn == TRUE) { if(!(name %in% dataNames)) { warning(paste0(firstWord, "! The column/value/argument, ", name, ", was not valid OR not in your data! Check your input! This is a warning message of that!")) } }
    if (warn == FALSE) { if(!(name %in% dataNames)) { stop(paste0(firstWord, "! The column/value/argument, " , name, ", was not valid OR not in your data! Check your input!")) } }

  }
}

#8


1  

Here's a quick and dirty way of inserting a column in a specific position on a data frame. In my case, I have 5 columns in the original data frame: c1, c2, c3, c4, c5 and I will insert a new column c2b between c2 and c3.

这里有一种快速而肮脏的方法,可以将列插入到数据帧的特定位置。在我的例子中,原始数据框架中有5列:c1、c2、c3、c4、c5,我将在c2和c3之间插入一个新的列c2b。

1) Let's first create the test data frame:

1)首先创建测试数据框架:

> dataset <- data.frame(c1 = 1:5, c2 = 2:6, c3=3:7, c4=4:8, c5=5:9)
> dataset
  c1 c2 c3 c4 c5
1  1  2  3  4  5
2  2  3  4  5  6
3  3  4  5  6  7
4  4  5  6  7  8
5  5  6  7  8  9

2) Add the new column c2b at the end of our data frame:

2)在数据帧的末尾添加新列c2b:

> dataset$c2b <- 10:14
> dataset
  c1 c2 c3 c4 c5 c2b
1  1  2  3  4  5  10
2  2  3  4  5  6  11
3  3  4  5  6  7  12
4  4  5  6  7  8  13
5  5  6  7  8  9  14

3) Reorder the data frame based on column indexes. In my case, I want to insert the new column (6) between existing columns 2 and 3. I do that by addressing the columns on my data frame using the vector c(1:2, 6, 3:5) which is equivalent to c(1, 2, 6, 3, 4, 5).

3)根据列索引对数据帧进行重新排序。在我的例子中,我想在现有的列2和3之间插入新的列(6)。我用向量c(1、2、6、3、5)来处理数据帧上的列,它等于c(1、2、6、3、4、5)。

> dataset <- dataset[,c(1:2, 6, 3:5)]
> dataset
  c1 c2 c2b c3 c4 c5
1  1  2  10  3  4  5
2  2  3  11  4  5  6
3  3  4  12  5  6  7
4  4  5  13  6  7  8
5  5  6  14  7  8  9

There!

在那里!

#9


1  

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)   
  }

#10


1  

Here is a an example of how to move a column from last to first position. It combines [ with ncol. I thought it would be useful to have a very short answer here for the busy reader:

这里有一个如何将列从最后一个位置移动到第一个位置的例子。它与ncol合并。我想在这里给忙碌的读者一个简短的回答会很有用:

d = mtcars
d[, c(ncol(d), 1:(ncol(d)-1))] 

#11


0  

`

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

`

#12


0  

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.

R没有指定在何处添加新列的功能。例如,美元mtcars mycol < -“foo”。它总是被添加到最后一列。使用其他方法(例如,dplyr的select())可以将mycol移动到所需的位置。这是不理想的,R可能想在将来改变它。

#13


0  

You can do it like below -

你可以像下面这样做

df <- data.frame(a=1:4, b=5:8, c=9:12)
df['d'] <- seq(10,13)
df <- df[,c('a','b','d','c')]

#1


33  

I would suggest you to use the function add_column() from the tibble package.

我建议您使用tibble包中的函数add_column()。

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.

或者使用参数。before而不是。after if更方便。

add_column(dataset, d = 4:8, .before = "c")

#2


26  

Just an R beginner, but I think this also works:

只是一个初学者,但我认为这也可以:

Add in your new column:

加入你的新专栏:

df$d <- list/data

Then you can reorder them.

然后你可以重新排序。

df <- df[,c("a","b","d","c")]

#3


19  

You can reorder the columns with [, or present the columns in the order that you want.

可以使用[对列进行重新排序,或者按所需的顺序显示列。

d <- data.frame(a=1:4, b=5:8, c=9:12)
target <- which(names(d) == 'b')[1]
cbind(d[,1:target,drop=F], data.frame(d=12:15), d[,(target+1):length(d),drop=F])

  a b  d  c
1 1 5 12  9
2 2 6 13 10
3 3 7 14 11
4 4 8 15 12

#4


10  

Presuming that c always immediately follows b, this code will add a column after b no matter where b is in your data.frame.

假设c总是紧跟着b,不管b在你的data.frame中的什么位置,这段代码都会在b之后添加一列。

> test <- data.frame(a=1,b=1,c=1)
> test
  a b c
1 1 1 1

> bspot <- which(names(test)=="b")

> data.frame(test[1:bspot],d=2,test[(bspot+1):ncol(test)])
  a b d c
1 1 1 2 1

Or possibly more naturally:

或者可能更自然:

data.frame(append(test, list(d=2), after=match("b", names(test))))

#5


4  

Create an example data.frame and add a column to it.

创建一个示例data.frame并向其添加一个列。

df = data.frame(a = seq(1, 3), b = seq(4,6), c = seq(7,9))
df['d'] <- seq(10,12)
df

  a b c  d
1 1 4 7 10
2 2 5 8 11
3 3 6 9 12

Rearrange by column index

重新排列的列索引

df[, colnames(df)[c(1:2,4,3)]]

or by column name

或列名

df[, c('a', 'b', 'd', 'c')]

The result is

结果是

  a b  d c
1 1 4 10 7
2 2 5 11 8
3 3 6 12 9

#6


3  

You would like to add column z to the old data frame (old.df) defined by columns x and y.

您希望将列z添加到由列x和y定义的旧数据帧(old.df)。

z = rbinom(1000, 5, 0.25)
old.df <- data.frame(x = c(1:1000), y = rnorm(1:1000))
head(old.df)

Define a new data frame called new.df

定义一个名为new.df的新数据帧

new.df <- data.frame(x = old.df[,1], z, y = old.df[,2])
head(new.df)

#7


2  

For what it's worth, I wrote a function to do this:

为了它的价值,我写了一个函数来做这个:

[removed]

(删除)


I have now updated this function with before and after functionality and defaulting place to 1. It also has data table compatability:

我现在已经更新了这个函数,之前和之后的功能和默认位置都是1。它也有数据表的兼容性:

#####
# FUNCTION: InsertDFCol(colName, colData, data, place = 1, before, after)
# DESCRIPTION: Takes in a data, a vector of data, a name for that vector and a place to insert this vector into
# the data frame as a new column. If you put place = 3, the new column will be in the 3rd position and push the current
# 3rd column up one (and each subsuquent column up one). All arguments must be set. Adding a before and after
# argument that will allow the user to say where to add the new column, before or after a particular column.
# Please note that if before or after is input, it WILL override the place argument if place is given as well. Also, place
# defaults to adding the new column to the front.
#####

InsertDFCol <- function(colName, colData, data, place = 1, before, after) {

  # A check on the place argument.
  if (length(names(data)) < place) stop("The place argument exceeds the number of columns in the data for the InsertDFCol function. Please check your place number")
  if (place <= 0 & (!missing(before) | !(missing(after)))) stop("You cannot put a column into the 0th or less than 0th position. Check your place argument.")
  if (place %% 1 != 0 & (!missing(before) | !(missing(after)))) stop("Your place value was not an integer.")
  if (!(missing(before)) & !missing(after)) stop("You cannot designate a before AND an after argument in the same function call. Please use only one or the other.")

  # Data Table compatability.
  dClass <- class(data)
  data <- as.data.frame(data)

  # Creating booleans to define whether before or after is given.
  useBefore <- !missing(before)
  useAfter <- !missing(after)

  # If either of these are true, then we are using the before or after argument, run the following code.
  if (useBefore | useAfter) {

    # Checking the before/after argument if given. Also adding regular expressions.
    if (useBefore) { CheckChoice(before, names(data)) ; before <- paste0("^", before, "$") }
    if (useAfter) { CheckChoice(after, names(data)) ; after <- paste0("^", after, "$") }

    # If before or after is given, replace "place" with the appropriate number.
    if (useBefore) { newPlace <- grep(before, names(data)) ; if (length(newPlace) > 1) { stop("Your before argument matched with more than one column name. Do you have duplicate column names?!") }}
    if (useAfter) { newPlace <- grep(after, names(data)) ; if (length(newPlace) > 1) { stop("Your after argument matched with more than one column name. Do you have duplicate column names?!") }}
    if (useBefore) place <- newPlace # Overriding place.
    if (useAfter) place <- newPlace + 1 # Overriding place.

  }

  # Making the new column.
  data[, colName] <- colData

  # Finding out how to reorder this.
  # The if statement handles the case where place = 1.
  currentPlace <- length(names(data)) # Getting the place of our data (which should have been just added at the end).
  if (place == 1) {

    colOrder <- c(currentPlace, 1:(currentPlace - 1))

  } else if (place == currentPlace) { # If the place to add the new data was just at the end of the data. Which is stupid...but we'll add support anyway.

    colOrder <- 1:currentPlace

  } else { # Every other case.

    firstHalf <- 1:(place - 1) # Finding the first half on columns that come before the insertion.
    secondHalf <- place:(currentPlace - 1) # Getting the second half, which comes after the insertion.
    colOrder <- c(firstHalf, currentPlace, secondHalf) # Putting that order together.

  }

  # Reordering the data.
  data <- subset(data, select = colOrder)

  # Data Table compatability.
  if (dClass[1] == "data.table") data <- as.data.table(data)

  # Returning.
  return(data)

}

I realized I also did not include CheckChoice:

我意识到我也没有包括CheckChoice:

#####
# FUNCTION: CheckChoice(names, dataNames, firstWord == "Oops" message = TRUE)                                                                                               
# DESCRIPTION: Takes the column names of a data frame and checks to make sure whatever "choice" you made (be it 
# your choice of dummies or your choice of chops) is actually in the data frame columns. Makes troubleshooting easier. 
# This function is also important in prechecking names to make sure the formula ends up being right. Use it after 
# adding in new data to check the "choose" options. Set firstWord to the first word you want said before an exclamation point.
# The warn argument (previously message) can be set to TRUE if you only want to 
#####

CheckChoice <- function(names, dataNames, firstWord = "Oops", warn = FALSE) {

  for (name in names) {

    if (warn == TRUE) { if(!(name %in% dataNames)) { warning(paste0(firstWord, "! The column/value/argument, ", name, ", was not valid OR not in your data! Check your input! This is a warning message of that!")) } }
    if (warn == FALSE) { if(!(name %in% dataNames)) { stop(paste0(firstWord, "! The column/value/argument, " , name, ", was not valid OR not in your data! Check your input!")) } }

  }
}

#8


1  

Here's a quick and dirty way of inserting a column in a specific position on a data frame. In my case, I have 5 columns in the original data frame: c1, c2, c3, c4, c5 and I will insert a new column c2b between c2 and c3.

这里有一种快速而肮脏的方法,可以将列插入到数据帧的特定位置。在我的例子中,原始数据框架中有5列:c1、c2、c3、c4、c5,我将在c2和c3之间插入一个新的列c2b。

1) Let's first create the test data frame:

1)首先创建测试数据框架:

> dataset <- data.frame(c1 = 1:5, c2 = 2:6, c3=3:7, c4=4:8, c5=5:9)
> dataset
  c1 c2 c3 c4 c5
1  1  2  3  4  5
2  2  3  4  5  6
3  3  4  5  6  7
4  4  5  6  7  8
5  5  6  7  8  9

2) Add the new column c2b at the end of our data frame:

2)在数据帧的末尾添加新列c2b:

> dataset$c2b <- 10:14
> dataset
  c1 c2 c3 c4 c5 c2b
1  1  2  3  4  5  10
2  2  3  4  5  6  11
3  3  4  5  6  7  12
4  4  5  6  7  8  13
5  5  6  7  8  9  14

3) Reorder the data frame based on column indexes. In my case, I want to insert the new column (6) between existing columns 2 and 3. I do that by addressing the columns on my data frame using the vector c(1:2, 6, 3:5) which is equivalent to c(1, 2, 6, 3, 4, 5).

3)根据列索引对数据帧进行重新排序。在我的例子中,我想在现有的列2和3之间插入新的列(6)。我用向量c(1、2、6、3、5)来处理数据帧上的列,它等于c(1、2、6、3、4、5)。

> dataset <- dataset[,c(1:2, 6, 3:5)]
> dataset
  c1 c2 c2b c3 c4 c5
1  1  2  10  3  4  5
2  2  3  11  4  5  6
3  3  4  12  5  6  7
4  4  5  13  6  7  8
5  5  6  14  7  8  9

There!

在那里!

#9


1  

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)   
  }

#10


1  

Here is a an example of how to move a column from last to first position. It combines [ with ncol. I thought it would be useful to have a very short answer here for the busy reader:

这里有一个如何将列从最后一个位置移动到第一个位置的例子。它与ncol合并。我想在这里给忙碌的读者一个简短的回答会很有用:

d = mtcars
d[, c(ncol(d), 1:(ncol(d)-1))] 

#11


0  

`

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

`

#12


0  

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.

R没有指定在何处添加新列的功能。例如,美元mtcars mycol < -“foo”。它总是被添加到最后一列。使用其他方法(例如,dplyr的select())可以将mycol移动到所需的位置。这是不理想的,R可能想在将来改变它。

#13


0  

You can do it like below -

你可以像下面这样做

df <- data.frame(a=1:4, b=5:8, c=9:12)
df['d'] <- seq(10,13)
df <- df[,c('a','b','d','c')]