Я убрал именование. Не похоже , чтобы добавить много, и в то время как Хедли перечислен как с автором пакета Кирилл Müller указан как создатель и сопровождающий .
Я считаю, что использование переупорядочения setcolorderв сочетании с номерами столбцов (в отличие от их имен) также очень полезно, потому что, как только количество столбцов становится очень большим, вы можете начать использовать seqи repвыполнять большую часть работы. Можно использовать плюс арифметические операторы. Напримерsetcolorder(data, c(1, (num_cols -2), (num_cols -1), num_cols, seq(from = 2, to = (num_cols - 3))))
n1k31t4
1
Я должен упомянуть, что setcolorderон предназначен для data.table, а не data.frame!
n1k31t4
21
Вы можете изменить порядок столбцов с помощью [, или расположить столбцы в желаемом порядке.
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
Это отличный ответ. Но я должен признать, что это также отличный пример того, почему R может быть трудным для новичков.
tumultous_rooster
2
При этом я думаю, что у @ ashah57 есть гораздо более простой и понятный ответ ниже. Не нужно слишком увлекаться чем-то вроде этого.
tumultous_rooster
12
Предполагая, что cвсегда следует сразу b, этот код добавит столбец после bнезависимо от того, где bнаходится ваш 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
Вот быстрый и грязный способ вставить столбец в определенную позицию во фрейме данных. В моем случае у меня есть 5 столбцов в исходном фрейме данных: c1, c2, c3, c4, c5и я вставлю новый столбец c2bмежду c2и c3.
3) Измените порядок фрейма данных на основе индексов столбцов. В моем случае я хочу вставить новый столбец (6) между существующими столбцами 2 и 3. Я делаю это, обращаясь к столбцам в моем фрейме данных, используя вектор, c(1:2, 6, 3:5)который эквивалентен c(1, 2, 6, 3, 4, 5).
Я обновил эту функцию, добавив beforeи, afterи по умолчанию placeустановил 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))
} 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)
}
Я понял, что также не включил 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!")) } }
}
}
Вот пример того, как переместить столбец из последней позиции в первую. Он сочетается [с ncol. Я подумал, что было бы полезно получить здесь очень короткий ответ для занятого читателя:
R не имеет возможности указать место добавления нового столбца. Например, mtcars$mycol<-'foo'. Он всегда добавляется как последний столбец. Используя другие средства (например, dplyr's select()), вы можете переместить микол в желаемое положение. Это не идеально, и R может попытаться изменить это в будущем.
Когда вы не можете предположить, что этот столбец bпоявляется раньше, cвы можете использовать его matchдля нахождения номера столбца обоих, minчтобы получить меньший номер столбца и seq_lenполучить последовательность до этого столбца. Затем вы можете сначала использовать этот индекс как положительное подмножество, затем разместить новый столбец, dа затем снова использовать последовательность как отрицательное подмножество.
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
Если вы знаете, что этот столбец bнаходится до cтого, как вы можете разместить новый столбец dпосле 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
Данные:
x <- data.frame(a = 1:3, b = 4:6, c = 7:9)
d <- 10:12
Ответы:
Я бы посоветовал вам воспользоваться функцией
add_column()
изtibble
пакета.library(tibble) dataset <- data.frame(a = 1:5, b = 2:6, c=3:7) add_column(dataset, d = 4:8, .after = 2)
Обратите внимание, что вы можете использовать имена столбцов вместо индекса столбца:
add_column(dataset, d = 4:8, .after = "b")
Или используйте аргумент
.before
вместо.after
более удобного.add_column(dataset, d = 4:8, .before = "c")
источник
Добавьте в свой новый столбец:
Затем вы можете изменить их порядок.
df <- df[, c("a", "b", "d", "c")]
источник
setcolorder
в сочетании с номерами столбцов (в отличие от их имен) также очень полезно, потому что, как только количество столбцов становится очень большим, вы можете начать использоватьseq
иrep
выполнять большую часть работы. Можно использовать плюс арифметические операторы. Напримерsetcolorder(data, c(1, (num_cols -2), (num_cols -1), num_cols, seq(from = 2, to = (num_cols - 3))))
setcolorder
он предназначен для data.table, а не data.frame!Вы можете изменить порядок столбцов с помощью [, или расположить столбцы в желаемом порядке.
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
источник
Предполагая, что
c
всегда следует сразуb
, этот код добавит столбец послеb
независимо от того, гдеb
находится ваш 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
Или, возможно, более естественно:
data.frame(append(test, list(d=2), after=match("b", names(test))))
источник
Создайте пример 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
Изменить порядок по индексу столбца
df[, colnames(df)[c(1:2,4,3)]]
или по названию столбца
df[, c('a', 'b', 'd', 'c')]
Результат
a b d c 1 1 4 10 7 2 2 5 11 8 3 3 6 12 9
источник
Вы хотите добавить столбец z в старый фрейм данных (old.df), определяемый столбцами x и y.
z = rbinom(1000, 5, 0.25) old.df <- data.frame(x = c(1:1000), y = rnorm(1:1000)) head(old.df)
Определите новый фрейм данных с именем new.df
new.df <- data.frame(x = old.df[,1], z, y = old.df[,2]) head(new.df)
источник
Вот быстрый и грязный способ вставить столбец в определенную позицию во фрейме данных. В моем случае у меня есть 5 столбцов в исходном фрейме данных:
c1, c2, c3, c4, c5
и я вставлю новый столбецc2b
междуc2
иc3
.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) Добавьте новый столбец
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) Измените порядок фрейма данных на основе индексов столбцов. В моем случае я хочу вставить новый столбец (6) между существующими столбцами 2 и 3. Я делаю это, обращаясь к столбцам в моем фрейме данных, используя вектор,
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
Там!
источник
Как бы то ни было, я написал для этого функцию:
[удалено]
Я обновил эту функцию, добавив
before
и,after
и по умолчаниюplace
установил 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) }
Я понял, что также не включил 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!")) } } } }
источник
Простое решение. Во фрейме данных с 5 столбцами, если вы хотите вставить еще один столбец между 3 и 4 ...
tmp <- data[, 1:3] tmp$example <- NA # or any value. data <- cbind(tmp, data[, 4:5]
источник
Эта функция вставляет один нулевой столбец между всеми существующими столбцами во фрейме данных.
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) }
источник
Вот пример того, как переместить столбец из последней позиции в первую. Он сочетается
[
сncol
. Я подумал, что было бы полезно получить здесь очень короткий ответ для занятого читателя:d = mtcars d[, c(ncol(d), 1:(ncol(d)-1))]
источник
Вы можете использовать эту
append()
функцию для вставки элементов в векторы или списки (фреймы данных - это списки). Просто: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))
Или, если вы хотите указать позицию по имени, используйте
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
`
источник
R не имеет возможности указать место добавления нового столбца. Например,
mtcars$mycol<-'foo'
. Он всегда добавляется как последний столбец. Используя другие средства (например,dplyr's select()
), вы можете переместить микол в желаемое положение. Это не идеально, и R может попытаться изменить это в будущем.источник
append
функция есть.Вы можете сделать это, как показано ниже -
df <- data.frame(a=1:4, b=5:8, c=9:12) df['d'] <- seq(10,13) df <- df[,c('a','b','d','c')]
источник
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)
полученные результаты
a b d c 1 1 3 0.5 5 2 2 4 1.0 6
Предлагаю использовать
dplyr::select
послеdplyr::mutate
. У него есть много помощников для выбора / отмены выбора подмножества столбцов.В контексте этого вопроса порядок, в котором вы выбираете, будет отражен в выходных данных data.frame.
источник
Когда вы не можете предположить, что этот столбец
b
появляется раньше,c
вы можете использовать егоmatch
для нахождения номера столбца обоих,min
чтобы получить меньший номер столбца иseq_len
получить последовательность до этого столбца. Затем вы можете сначала использовать этот индекс как положительное подмножество, затем разместить новый столбец,d
а затем снова использовать последовательность как отрицательное подмножество.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
Если вы знаете, что этот столбец
b
находится доc
того, как вы можете разместить новый столбецd
после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
Данные:
x <- data.frame(a = 1:3, b = 4:6, c = 7:9) d <- 10:12
источник