Usunąłem zrzucanie nazw. Nie wydaje się, aby dodać dużo, a podczas Hadley jest wymieniony jako na autora pakietu Kirill Müller jest wymieniony jako twórcy i opiekuna .
Uważam, że zmiana kolejności używania setcolorderw połączeniu z numerami kolumn (w przeciwieństwie do ich nazw) również jest bardzo przydatna, ponieważ gdy liczba kolumn stanie się bardzo duża, możesz zacząć używać seqi repwykonywać większość pracy. Można również stosować operatory arytmetyczne. Np.setcolorder(data, c(1, (num_cols -2), (num_cols -1), num_cols, seq(from = 2, to = (num_cols - 3))))
n1k31t4
1
Powinienem wspomnieć, że setcolorderjest przeznaczony dla tabeli danych, a nie ramki danych!
n1k31t4
21
Możesz zmienić kolejność kolumn za pomocą [lub przedstawić kolumny w żądanej kolejności.
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 c115129226131033714114481512
To świetna odpowiedź. Ale muszę przyznać, że jest to również świetny przykład tego, dlaczego R może być trudny dla początkujących.
tumultous_rooster
2
Biorąc to pod uwagę, myślę, że @ ashah57 ma znacznie prostszą i czystszą odpowiedź poniżej. Nie ma potrzeby, aby coś takiego wyglądało jak to.
tumultous_rooster
12
Zakładając, że czawsze następuje bto natychmiast , ten kod doda kolumnę po każdym bmiejscu bw data.frame.
> test <- data.frame(a=1,b=1,c=1)
> test
a b c1111
> bspot <- which(names(test)=="b")
> data.frame(test[1:bspot],d=2,test[(bspot+1):ncol(test)])
a b d c11121
Oto szybki i brudny sposób wstawiania kolumny w określonej pozycji w ramce danych. W moim przypadku mam 5 kolumn w oryginalnej ramce danych: c1, c2, c3, c4, c5i wstawię nową kolumnę c2bmiędzy c2a c3.
3) Zmień kolejność ramki danych na podstawie indeksów kolumn. W moim przypadku chcę wstawić nową kolumnę (6) między istniejące kolumny 2 i 3. Robię to, adresując kolumny w mojej ramce danych za pomocą wektora, c(1:2, 6, 3:5)który jest równoważny c(1, 2, 6, 3, 4, 5).
Mam teraz zaktualizowane z tej funkcji beforei afterfunkcjonalność i zalegających placena 1. Posiada również tabeli danych kompatybilność:
###### 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)
}
Zdałem sobie sprawę, że nie uwzględniłem też 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 innames) {
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!")) } }
}
}
Oto przykład, jak przenieść kolumnę z ostatniej na pierwszą pozycję. Łączy się [z ncol. Pomyślałem, że przydałaby się tutaj bardzo krótka odpowiedź dla zajętego czytelnika:
R nie ma funkcji określania miejsca dodawania nowej kolumny. Np mtcars$mycol<-'foo'. Zawsze jest dodawany jako ostatnia kolumna. Używając innych środków (np. dplyr's select()) Możesz przesunąć mykol do żądanej pozycji. To nie jest idealne rozwiązanie i R może chcieć to zmienić w przyszłości.
Kiedy nie możesz założyć, że kolumna bwystępuje wcześniej c, możesz użyć matchdo znalezienia numeru kolumny obu, minaby uzyskać niższy numer kolumny i seq_lenuzyskać sekwencję do tej kolumny. Następnie możesz najpierw użyć tego indeksu jako podzbioru dodatniego , następnie umieścić nową kolumnę, da następnie użyć sekwencji ponownie jako podzbioru ujemnego .
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
W przypadku, gdy wiesz, że kolumna bpojawi się przed cumieszczeniem nowej kolumny dpo 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
Dane:
x <- data.frame(a = 1:3, b = 4:6, c = 7:9)
d <- 10:12
Odpowiedzi:
Proponuję skorzystać z funkcji
add_column()
ztibble
pakietu.library(tibble) dataset <- data.frame(a = 1:5, b = 2:6, c=3:7) add_column(dataset, d = 4:8, .after = 2)
Zauważ, że możesz użyć nazw kolumn zamiast indeksu kolumn:
add_column(dataset, d = 4:8, .after = "b")
Lub użyj argumentu
.before
zamiast,.after
jeśli wygodniej.add_column(dataset, d = 4:8, .before = "c")
źródło
Dodaj w nowej kolumnie:
df$d <- list/data
Następnie możesz je ponownie zamówić.
df <- df[, c("a", "b", "d", "c")]
źródło
setcolorder
w połączeniu z numerami kolumn (w przeciwieństwie do ich nazw) również jest bardzo przydatna, ponieważ gdy liczba kolumn stanie się bardzo duża, możesz zacząć używaćseq
irep
wykonywać większość pracy. Można również stosować operatory arytmetyczne. Np.setcolorder(data, c(1, (num_cols -2), (num_cols -1), num_cols, seq(from = 2, to = (num_cols - 3))))
setcolorder
jest przeznaczony dla tabeli danych, a nie ramki danych!Możesz zmienić kolejność kolumn za pomocą [lub przedstawić kolumny w żądanej kolejności.
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
źródło
Zakładając, że
c
zawsze następujeb
to natychmiast , ten kod doda kolumnę po każdymb
miejscub
w 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
Lub bardziej naturalnie:
data.frame(append(test, list(d=2), after=match("b", names(test))))
źródło
Utwórz przykładową ramkę data.frame i dodaj do niej kolumnę.
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
Zmień kolejność według indeksu kolumn
df[, colnames(df)[c(1:2,4,3)]]
lub według nazwy kolumny
df[, c('a', 'b', 'd', 'c')]
Wynik to
a b d c 1 1 4 10 7 2 2 5 11 8 3 3 6 12 9
źródło
Chciałbyś dodać kolumnę z do starej ramki danych (stary.df) zdefiniowanej przez kolumny x i y.
z = rbinom(1000, 5, 0.25) old.df <- data.frame(x = c(1:1000), y = rnorm(1:1000)) head(old.df)
Zdefiniuj nową ramkę danych o nazwie new.df
new.df <- data.frame(x = old.df[,1], z, y = old.df[,2]) head(new.df)
źródło
Oto szybki i brudny sposób wstawiania kolumny w określonej pozycji w ramce danych. W moim przypadku mam 5 kolumn w oryginalnej ramce danych:
c1, c2, c3, c4, c5
i wstawię nową kolumnęc2b
międzyc2
ac3
.1) Najpierw utwórzmy ramkę danych testowych:
> 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) Dodaj nową kolumnę
c2b
na końcu naszej ramki danych:> 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) Zmień kolejność ramki danych na podstawie indeksów kolumn. W moim przypadku chcę wstawić nową kolumnę (6) między istniejące kolumny 2 i 3. Robię to, adresując kolumny w mojej ramce danych za pomocą wektora,
c(1:2, 6, 3:5)
który jest równoważnyc(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
Tam!
źródło
Na co warto napisałem funkcję, aby to zrobić:
[oddalony]
Mam teraz zaktualizowane z tej funkcji
before
iafter
funkcjonalność i zalegającychplace
na 1. Posiada również tabeli danych kompatybilność:##### # 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) }
Zdałem sobie sprawę, że nie uwzględniłem też 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!")) } } } }
źródło
Proste rozwiązanie. W ramce danych z 5 kolumnami, jeśli chcesz wstawić kolejną kolumnę między 3 a 4 ...
tmp <- data[, 1:3] tmp$example <- NA # or any value. data <- cbind(tmp, data[, 4:5]
źródło
Ta funkcja wstawia jedną kolumnę zerową między wszystkie wcześniej istniejące kolumny w ramce danych.
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) }
źródło
Oto przykład, jak przenieść kolumnę z ostatniej na pierwszą pozycję. Łączy się
[
zncol
. Pomyślałem, że przydałaby się tutaj bardzo krótka odpowiedź dla zajętego czytelnika:d = mtcars d[, c(ncol(d), 1:(ncol(d)-1))]
źródło
Możesz użyć tej
append()
funkcji, aby wstawić elementy do wektorów lub list (ramki danych to listy). Po prostu: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))
Lub, jeśli chcesz określić pozycję według nazwy, użyj
which
:df <- as.data.frame(append(df, list(d=df$b+df$c), after=which(names(df)=="b")))
źródło
`
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ódło
R nie ma funkcji określania miejsca dodawania nowej kolumny. Np
mtcars$mycol<-'foo'
. Zawsze jest dodawany jako ostatnia kolumna. Używając innych środków (np.dplyr's select()
) Możesz przesunąć mykol do żądanej pozycji. To nie jest idealne rozwiązanie i R może chcieć to zmienić w przyszłości.źródło
append
funkcję.Możesz to zrobić jak poniżej -
df <- data.frame(a=1:4, b=5:8, c=9:12) df['d'] <- seq(10,13) df <- df[,c('a','b','d','c')]
źródło
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)
wyniki
a b d c 1 1 3 0.5 5 2 2 4 1.0 6
Proponuję użyć
dplyr::select
podplyr::mutate
. Ma wielu pomocników do zaznaczania / usuwania zaznaczenia podzbioru kolumn.W kontekście tego pytania kolejność wyboru zostanie odzwierciedlona w wyjściowej ramce data.frame.
źródło
Kiedy nie możesz założyć, że kolumna
b
występuje wcześniejc
, możesz użyćmatch
do znalezienia numeru kolumny obu,min
aby uzyskać niższy numer kolumny iseq_len
uzyskać sekwencję do tej kolumny. Następnie możesz najpierw użyć tego indeksu jako podzbioru dodatniego , następnie umieścić nową kolumnę,d
a następnie użyć sekwencji ponownie jako podzbioru ujemnego .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
W przypadku, gdy wiesz, że kolumna
b
pojawi się przedc
umieszczeniem nowej kolumnyd
pob
: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
Dane:
x <- data.frame(a = 1:3, b = 4:6, c = 7:9) d <- 10:12
źródło