2012-11-21 15 views
41

Ho un frame di dati con le colonne a, b e c. Vorrei aggiungere una nuova colonna d tra b e c. So che potrei semplicemente aggiungere d alla fine usando cbind ma come posso inserirlo tra due colonne?Aggiunta di una colonna tra due colonne in un data.frame

+0

Forse questo fa ciò che si vuole: http://r.789695.n4.nabble.com/How-to-insert-a-column-in-a-data-frame-td883724.html –

+1

fa la funzione mutate() nel pacchetto dplyr consente di aggiungere colonne come indicato in questa domanda? – marbel

risposta

19

È possibile riordinare le colonne con [, o presentare le colonne nell'ordine desiderato.

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 
+9

Questa è un'ottima risposta. Ma devo ammettere che questo è anche un ottimo esempio del perché R può essere difficile per i principianti. –

+1

Detto questo, penso che @ ashah57 abbia una risposta molto più semplice e pulita qui sotto. Non c'è bisogno di essere troppo stravaganti per qualcosa di simile. –

10

Presumendo che c sempre segue immediatamente b, questo codice aggiungere una colonna dopo b non importa dove b è nel vostro 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 

O forse in modo più naturale:

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

Solo un principiante R, ma credo che questo funziona anche:

Aggiungi nella tua nuova colonna:

df$d <- list/data 

Poi si puoi riordinarli.

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

df <- df [c ("a", "b", "d", "c")] funziona anche con –

+1

Trovo che riordino usando 'setcolorder' insieme ai numeri di colonna (in contrapposizione ai loro nomi) anche molto utile, perché una volta che il numero di colonne diventa molto grande, puoi iniziare a usare 'seq' e' rep'per fare la maggior parte del lavoro. Possono essere utilizzati anche operatori aritmetici. Per esempio.'setcolorder (data, c (1, (num_cols -2), (num_cols -1), num_cols, seq (da = 2 a = (num_cols - 3))))' –

+1

Dovrei menzionare, 'setcolorder' è inteso per un data.table, non un data.frame! –

3

Si desidera aggiungere colonna z al vecchio frame di dati (old.df) definito dalle colonne x ed y.

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

definire un nuovo riquadro di dati chiamato new.df

new.df <- data.frame(x = old.df[,1], z, y = old.df[,2]) 
head(new.df) 
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 

`

2

Per quello che vale, ho scritto una funzione per fare questo:

[rimosso]


ho ora aggiornato questa funzione con before e after funzionalità e inadempiente place a 1. Ha anche tabella di dati compatibilità:

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

} 

ho capito anche io non ho incluso 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!")) } } 

    } 
} 
0

Ecco un modo veloce e sporco di inserire una colonna in una posizione specifica su un frame di dati. Nel mio caso, ho 5 colonne nel frame di dati originale: c1, c2, c3, c4, c5 e inserirò una nuova colonna c2b tra c2 e c3.

1) Facciamo prima creare il frame di dati di test:

> 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) Aggiungere la nuova colonna c2b alla fine della nostra struttura dei dati:

> 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) riordinare i frame di dati base sugli indici delle colonne. Nel mio caso, voglio inserire la nuova colonna (6) tra le colonne esistenti 2 e 3. Lo faccio indirizzando le colonne sulla mia cornice dati usando il vettore c(1:2, 6, 3:5) che equivale a 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 

Là!

1

Questa funzione inserisce una colonna zero tra tutte le colonne preesistenti in un frame di dati.

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

R non ha alcuna funzionalità per specificare dove viene aggiunta una nuova colonna. Ad esempio, mtcars$mycol<-'foo'. Viene sempre aggiunto come ultima colonna. Usando altri mezzi (ad esempio, dplyr's select()) è possibile spostare il mycol nella posizione desiderata. Questo non è l'ideale e R potrebbe voler provare a cambiarlo in futuro.

3

Creare un esempio data.frame e aggiungere una colonna ad esso.

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 

Riorganizza da indice della colonna

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

o nome di colonna

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

Il risultato è

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

io vi suggerisco di utilizzare la funzione di add_column() dal tibble pacchetto.

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

noti che è possibile utilizzare nomi di colonna al posto di indice della colonna:

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

O uso argomento .before invece di .after se più conveniente.

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

Ho rimosso il name-drop. Non sembra aggiungere molto, e mentre Hadley è elencato come * un * autore del pacchetto Kirill Müller è elencato come [creatore e manutentore] (https://cran.r-project.org/web/packages/tibble/ index.html). – Gregor

+0

Questo mi aiuta, grazie – cloudscomputes

Problemi correlati