Eu removi a citação de nomes. Não parece acrescentar muito, e enquanto Hadley é listado como um autor do pacote Kirill Müller é listado como criador e mantenedor .
Acho que reordenar o uso setcolorderem conjunto com os números das colunas (em oposição aos seus nomes) também é muito útil, porque, uma vez que o número de colunas se torne muito grande, você pode começar a usar seqe repfazer a maior parte do trabalho. Além disso, os operadores aritméticos podem ser usados. Por exemplosetcolorder(data, c(1, (num_cols -2), (num_cols -1), num_cols, seq(from = 2, to = (num_cols - 3))))
n1k31t4
1
Devo mencionar que setcolorderse destina a data.table, não a data.frame!
n1k31t4
21
Você pode reordenar as colunas com [ou apresentar as colunas na ordem que desejar.
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
115129226131033714114481512
Esta é uma ótima resposta. Mas tenho que admitir, esse também é um ótimo exemplo de por que o R pode ser difícil para iniciantes.
tumultous_rooster
2
Dito isso, acho que @ ashah57 tem uma resposta muito mais simples e limpa abaixo. Não há necessidade de ficar muito extravagante com algo assim.
tumultous_rooster
12
Presumindo que csempre segue imediatamente b, este código adicionará uma coluna após, bnão importa onde besteja em seu data.frame.
> test <- data.frame(a=1,b=1,c=1)
> test
a b c
1111
> bspot <- which(names(test)=="b")
> data.frame(test[1:bspot],d=2,test[(bspot+1):ncol(test)])
a b d c
11121
Esta é uma maneira rápida e suja de inserir uma coluna em uma posição específica em um quadro de dados. No meu caso, tenho 5 colunas no quadro de dados original: c1, c2, c3, c4, c5e irei inserir uma nova coluna c2bentre c2e c3.
1) Vamos primeiro criar o quadro de dados de teste:
3) Reordene o quadro de dados com base nos índices da coluna. No meu caso, quero inserir a nova coluna (6) entre as colunas existentes 2 e 3. Faço isso endereçando as colunas em meu quadro de dados usando o vetor c(1:2, 6, 3:5)que é equivalente a c(1, 2, 6, 3, 4, 5).
Pelo que vale a pena, escrevi uma função para fazer isso:
[removido]
Eu já atualizou esta função com beforee afterfuncionalidade e falta placea 1. Ele também tem compatibilidade tabela de dados:
###### 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))
} elseif (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)
}
Percebi que também não incluí 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!")) } }
}
}
Aqui está um exemplo de como mover uma coluna da última para a primeira posição. Combina [com ncol. Achei que seria útil ter uma resposta muito curta aqui para o leitor ocupado:
R não tem funcionalidade para especificar onde uma nova coluna é adicionada. Por exemplo, mtcars$mycol<-'foo'. É sempre adicionado como última coluna. Usando outros meios (por exemplo, dplyr's select()) você pode mover o mycol para a posição desejada. Isso não é ideal e R pode querer tentar mudar isso no futuro.
Quando você não pode assumir que a coluna bvem antes, cvocê pode usar matchpara encontrar o número da coluna de ambas, minpara obter o número da coluna mais baixo e seq_lenpara obter uma sequência até esta coluna. Em seguida, você pode usar este índice primeiro como um subconjunto positivo , em dseguida , coloque a nova coluna e, em seguida, use a sequência novamente como um subconjunto negativo .
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
Caso você saiba que a coluna bvem antes, cvocê pode colocar a nova coluna ddepois de 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
Dados:
x <- data.frame(a = 1:3, b = 4:6, c = 7:9)
d <- 10:12
Respostas:
Eu sugiro que você use a função
add_column()
dotibble
pacote.library(tibble) dataset <- data.frame(a = 1:5, b = 2:6, c=3:7) add_column(dataset, d = 4:8, .after = 2)
Observe que você pode usar nomes de coluna em vez de índice de coluna:
add_column(dataset, d = 4:8, .after = "b")
Ou use o argumento em
.before
vez de.after
se for mais conveniente.add_column(dataset, d = 4:8, .before = "c")
fonte
Adicione em sua nova coluna:
Então você pode reordená-los.
df <- df[, c("a", "b", "d", "c")]
fonte
setcolorder
em conjunto com os números das colunas (em oposição aos seus nomes) também é muito útil, porque, uma vez que o número de colunas se torne muito grande, você pode começar a usarseq
erep
fazer a maior parte do trabalho. Além disso, os operadores aritméticos podem ser usados. Por exemplosetcolorder(data, c(1, (num_cols -2), (num_cols -1), num_cols, seq(from = 2, to = (num_cols - 3))))
setcolorder
se destina a data.table, não a data.frame!Você pode reordenar as colunas com [ou apresentar as colunas na ordem que desejar.
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
fonte
Presumindo que
c
sempre segue imediatamenteb
, este código adicionará uma coluna após,b
não importa ondeb
esteja em seu 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
Ou possivelmente mais naturalmente:
data.frame(append(test, list(d=2), after=match("b", names(test))))
fonte
Crie um exemplo data.frame e adicione uma coluna a ele.
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
Reorganizar por índice de coluna
df[, colnames(df)[c(1:2,4,3)]]
ou pelo nome da coluna
df[, c('a', 'b', 'd', 'c')]
O resultado é
a b d c 1 1 4 10 7 2 2 5 11 8 3 3 6 12 9
fonte
Você gostaria de adicionar a coluna z ao quadro de dados antigo (old.df) definido pelas colunas x e y.
z = rbinom(1000, 5, 0.25) old.df <- data.frame(x = c(1:1000), y = rnorm(1:1000)) head(old.df)
Defina um novo quadro de dados chamado new.df
new.df <- data.frame(x = old.df[,1], z, y = old.df[,2]) head(new.df)
fonte
Esta é uma maneira rápida e suja de inserir uma coluna em uma posição específica em um quadro de dados. No meu caso, tenho 5 colunas no quadro de dados original:
c1, c2, c3, c4, c5
e irei inserir uma nova colunac2b
entrec2
ec3
.1) Vamos primeiro criar o quadro de dados de teste:
> 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) Adicione a nova coluna
c2b
no final do nosso quadro de dados:> 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) Reordene o quadro de dados com base nos índices da coluna. No meu caso, quero inserir a nova coluna (6) entre as colunas existentes 2 e 3. Faço isso endereçando as colunas em meu quadro de dados usando o vetor
c(1:2, 6, 3:5)
que é equivalente ac(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á!
fonte
Pelo que vale a pena, escrevi uma função para fazer isso:
[removido]
Eu já atualizou esta função com
before
eafter
funcionalidade e faltaplace
a 1. Ele também tem compatibilidade tabela de dados:##### # 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) }
Percebi que também não incluí 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!")) } } } }
fonte
Solução fácil. Em um quadro de dados com 5 colunas, se você deseja inserir outra coluna entre 3 e 4 ...
tmp <- data[, 1:3] tmp$example <- NA # or any value. data <- cbind(tmp, data[, 4:5]
fonte
Esta função insere uma coluna zero entre todas as colunas preexistentes em um quadro de dados.
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) }
fonte
Aqui está um exemplo de como mover uma coluna da última para a primeira posição. Combina
[
comncol
. Achei que seria útil ter uma resposta muito curta aqui para o leitor ocupado:d = mtcars d[, c(ncol(d), 1:(ncol(d)-1))]
fonte
Você pode usar a
append()
função para inserir itens em vetores ou listas (dataframes são listas). Simplesmente: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))
Ou, se você deseja especificar a posição por nome, use
which
:df <- as.data.frame(append(df, list(d=df$b+df$c), after=which(names(df)=="b")))
fonte
`
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
`
fonte
R não tem funcionalidade para especificar onde uma nova coluna é adicionada. Por exemplo,
mtcars$mycol<-'foo'
. É sempre adicionado como última coluna. Usando outros meios (por exemplo,dplyr's select()
) você pode mover o mycol para a posição desejada. Isso não é ideal e R pode querer tentar mudar isso no futuro.fonte
append
função.Você pode fazer como abaixo -
df <- data.frame(a=1:4, b=5:8, c=9:12) df['d'] <- seq(10,13) df <- df[,c('a','b','d','c')]
fonte
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)
resultados
a b d c 1 1 3 0.5 5 2 2 4 1.0 6
Eu sugiro usar
dplyr::select
depoisdplyr::mutate
. Possui muitos auxiliares para selecionar / desmarcar subconjunto de colunas.No contexto desta questão, a ordem pela qual você seleciona será refletida no data.frame de saída.
fonte
Quando você não pode assumir que a coluna
b
vem antes,c
você pode usarmatch
para encontrar o número da coluna de ambas,min
para obter o número da coluna mais baixo eseq_len
para obter uma sequência até esta coluna. Em seguida, você pode usar este índice primeiro como um subconjunto positivo , emd
seguida , coloque a nova coluna e, em seguida, use a sequência novamente como um subconjunto negativo .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
Caso você saiba que a coluna
b
vem antes,c
você pode colocar a nova colunad
depois deb
: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
Dados:
x <- data.frame(a = 1:3, b = 4:6, c = 7:9) d <- 10:12
fonte