Fügen Sie eine Spalte zwischen zwei Spalten in einem data.frame hinzu (fügen Sie sie ein)

84

Ich habe einen Datenrahmen mit den Spalten a, b und c. Ich möchte eine neue Spalte d zwischen b und c hinzufügen.

Ich weiß, dass ich mit cbind am Ende einfach d hinzufügen könnte, aber wie kann ich es zwischen zwei Spalten einfügen ?

Kennzeichen
quelle
Vielleicht macht das, was Sie wollen: r.789695.n4.nabble.com/…
Mark Miller
1
Ermöglicht die Funktion mutate () im Paket dplyr das Hinzufügen von Spalten, wie in dieser Frage angegeben?
Marbel

Antworten:

78

Ich würde Ihnen empfehlen, die Funktion add_column()aus dem tibblePaket zu verwenden.

library(tibble)
dataset <- data.frame(a = 1:5, b = 2:6, c=3:7)
add_column(dataset, d = 4:8, .after = 2)

Beachten Sie, dass Sie anstelle des Spaltenindex Spaltennamen verwenden können:

add_column(dataset, d = 4:8, .after = "b")

Oder verwenden Sie ein Argument, .beforeanstatt .afteres bequemer zu machen.

add_column(dataset, d = 4:8, .before = "c")
Kevin Zarca
quelle
6
Ich habe das Löschen des Namens entfernt. Scheint nicht viel hinzuzufügen, und während Hadley als aufgeführt ist ein Autor des Pakets Kirill Müller wird als aufgeführter Schöpfer und Erhalter .
Gregor Thomas
36

Fügen Sie in Ihrer neuen Spalte hinzu:

df$d <- list/data

Dann können Sie sie nachbestellen.

df <- df[, c("a", "b", "d", "c")]
ashah57
quelle
1
Ich finde die Neuordnung setcolorderin Verbindung mit Spaltennummern (im Gegensatz zu ihren Namen) ebenfalls sehr nützlich, da Sie, sobald die Anzahl der Spalten sehr groß wird, mit der Verwendung beginnen seqund repden größten Teil der Arbeit erledigen können. Außerdem können arithmetische Operatoren verwendet werden. ZBsetcolorder(data, c(1, (num_cols -2), (num_cols -1), num_cols, seq(from = 2, to = (num_cols - 3))))
n1k31t4
1
Ich sollte erwähnen, setcolorderist für eine data.table gedacht, nicht für einen data.frame!
n1k31t4
21

Sie können die Spalten mit [neu anordnen oder die Spalten in der gewünschten Reihenfolge anzeigen.

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
Matthew Lundberg
quelle
13
Dies ist eine großartige Antwort. Aber ich muss zugeben, dies ist auch ein großartiges Beispiel dafür, warum R für Anfänger schwierig sein kann.
tumultous_rooster
2
Davon abgesehen denke ich, dass @ ashah57 unten eine viel einfachere und sauberere Antwort hat. Bei so etwas muss man nicht zu ausgefallen sein.
tumultous_rooster
12

Vorausgesetzt, dass dies cimmer unmittelbar folgt b, fügt dieser Code eine Spalte hinzu, begal wo bin Ihrem data.frame.

> 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

Oder vielleicht natürlicher:

data.frame(append(test, list(d=2), after=match("b", names(test))))
die E-Mail
quelle
4

Erstellen Sie ein Beispiel für data.frame und fügen Sie eine Spalte hinzu.

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

Nach Spaltenindex neu anordnen

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

oder nach Spaltenname

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

Das Ergebnis ist

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

Sie möchten dem alten Datenrahmen (old.df), der durch die Spalten x und y definiert ist, die Spalte z hinzufügen.

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

Definieren Sie einen neuen Datenrahmen mit dem Namen new.df.

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

Für das, was es wert ist, habe ich eine Funktion geschrieben, um dies zu tun:

[entfernt]


Ich habe diese Funktion jetzt mit beforeund afterFunktionalität aktualisiert und standardmäßig placeauf 1 gesetzt. Sie ist auch mit Datentabellen kompatibel:

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

}

Mir wurde klar, dass ich CheckChoice auch nicht aufgenommen habe:

#####
# 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!")) } }

  }
}
Giraffehere
quelle
2

Einfache Lösung. Wenn Sie in einem Datenrahmen mit 5 Spalten eine weitere Spalte zwischen 3 und 4 einfügen möchten ...

tmp <- data[, 1:3]
tmp$example <- NA # or any value.
data <- cbind(tmp, data[, 4:5]
Jose Luis Camps
quelle
1

Hier ist eine schnelle und schmutzige Methode zum Einfügen einer Spalte an einer bestimmten Position in einem Datenrahmen. In meinem Fall habe ich 5 Spalten im ursprünglichen Datenrahmen: c1, c2, c3, c4, c5und ich werde eine neue Spalte c2bzwischen c2und einfügen c3.

1) Erstellen wir zunächst den Testdatenrahmen:

> 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) Fügen Sie die neue Spalte c2bam Ende unseres Datenrahmens hinzu:

> 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) Ordnen Sie den Datenrahmen basierend auf Spaltenindizes neu an. In meinem Fall möchte ich die neue Spalte (6) zwischen die vorhandenen Spalten 2 und 3 einfügen. Dazu adressiere ich die Spalten in meinem Datenrahmen mit dem Vektor, c(1:2, 6, 3:5)der äquivalent zu ist 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

Dort!

Ricardo
quelle
1

Diese Funktion fügt eine Nullspalte zwischen allen bereits vorhandenen Spalten in einem Datenrahmen ein.

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)   
  }
Gabriel Tadeo del Campo
quelle
1

Hier ist ein Beispiel, wie eine Spalte von der letzten zur ersten Position verschoben wird. Es verbindet sich [mit ncol. Ich dachte, es wäre nützlich, hier eine sehr kurze Antwort für den vielbeschäftigten Leser zu haben:

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

Mit dieser append()Funktion können Sie Elemente in Vektoren oder Listen einfügen (Datenrahmen sind Listen). Einfach:

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

Oder wenn Sie die Position nach Namen angeben möchten, verwenden Sie which:

df <- as.data.frame(append(df, list(d=df$b+df$c), after=which(names(df)=="b")))
Simon Woodward
quelle
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

`

Iordanov K.
quelle
0

R hat keine Funktionalität, um anzugeben, wo eine neue Spalte hinzugefügt wird. ZB , mtcars$mycol<-'foo'. Es wird immer als letzte Spalte hinzugefügt. Mit anderen Mitteln (z. B. dplyr's select()) können Sie das Mycol an eine gewünschte Position bringen. Dies ist nicht ideal und R möchte möglicherweise versuchen, dies in Zukunft zu ändern.

userJT
quelle
Ja, es hat die appendFunktion.
Simon Woodward
0

Sie können es wie unten tun -

df <- data.frame(a=1:4, b=5:8, c=9:12)
df['d'] <- seq(10,13)
df <- df[,c('a','b','d','c')]
Tanvir ahmad
quelle
0
df <- data.frame(a=c(1,2), b=c(3,4), c=c(5,6))
df %>%
  mutate(d= a/2) %>%
  select(a, b, d, c)

Ergebnisse

  a b   d c
1 1 3 0.5 5
2 2 4 1.0 6

Ich schlage vor, dplyr::selectnach zu verwenden dplyr::mutate. Es gibt viele Helfer zum Auswählen / Deaktivieren einer Teilmenge von Spalten.

Im Kontext dieser Frage wird die Reihenfolge, in der Sie auswählen, im Ausgabedatenrahmen wiedergegeben.

Kresten
quelle
0

Wenn Sie nicht davon ausgehen können, dass diese Spalte bvor cIhnen steht, können matchSie die Spaltennummer von beiden ermitteln, mindie niedrigere Spaltennummer abrufen und seq_leneine Sequenz bis zu dieser Spalte abrufen. Dann können Sie diesen Index zuerst als positive Teilmenge verwenden, dann die neue Spalte platzieren dund dann die Sequenz erneut als negative Teilmenge verwenden.

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

Für den Fall , wissen Sie , dass Spalte bkommt , bevor cSie die neue Spalte platzieren können dnach 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

Daten:

x <- data.frame(a = 1:3, b = 4:6, c = 7:9)
d <- 10:12
GKi
quelle