Veri çerçevesindeki sütunlar nasıl yeniden sıralanır?


311

Bu giriş nasıl değiştirilir (dizi, zaman, giriş, çıkış, dosyalar ile):

Time   In    Out  Files
1      2     3    4
2      3     4    5

Bu çıktıya (sıra ile: zaman, çıkış, giriş, dosyalar)?

Time   Out   In  Files
1      3     2    4
2      4     3    5

İşte kukla R verileri:

table <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5))
table
##  Time In Out Files
##1    1  2   3     4
##2    2  3   4     5

4
help(Extract)olarak da bilinir?'['
Joris Meys

3
@ Joris'in önerisine ek olarak, "R'ye Giriş" kılavuzunun 2.7 ve 5. bölümlerini okumaya çalışın: cran.r-project.org/doc/manuals/R-intro.html
Gavin Simpson

3
Ek bir sorun: tüm yanıtlar sütunların tam listesini gerektirir, aksi takdirde alt kümeye neden olurlar. Ya yalnızca ilk sütun olarak sipariş edilecek birkaç sütun listelemek istiyorsak, aynı zamanda diğerlerini de tutmak istiyorsak?
000andy8484

Yanıtlar:


341

Veri çerçevenizde dört sütun vardır df[,c(1,2,3,4)]. İlk virgülün tüm satırları koruyacağını ve 1,2,3,4'ün sütunları ifade ettiğini unutmayın.

Yukarıdaki sorudaki gibi sırayı değiştirmek için df2[,c(1,3,2,4)]

Bu dosyayı csv olarak çıkarmak istiyorsanız, write.csv(df2, file="somedf.csv")


35
Sınırlı sayıda sütununuz olduğunda bu sorun olmaz, ancak örneğin 50 sütununuz varsa, tüm sütun numaralarını veya adlarını yazmak çok fazla zaman alır. Daha hızlı bir çözüm ne olurdu?
Herman Toothrot

54
@ user4050: bu durumda ":" sözdizimini kullanabilirsiniz, örneğin df [, c (1,3,2,4,5: 50)].
dalloliogm

1
sütunları başlangıçta idcols'a koymak için: idcols <- c ("ad", "id2", "başlangıç", "süre"); cols <- c (idcols, adlar (cts) [- hangi (% idcols içinde adlar (cts)%)]); df <- df [cols]
kasterma

13
@ user4050: df[,c(1,3,2,4:ncol(df))]kaç sütun olduğunu bilmediğinizde de kullanabilirsiniz .
arekolek

1
Ayrıca dput (colnames (df)) kullanabilirsiniz, sütun adlarını R karakter biçiminde yazdırır. Daha sonra adları yeniden düzenleyebilirsiniz.
Chris

168
# reorder by column name
data <- data[c("A", "B", "C")]

#reorder by column index
data <- data[c(1,3,2)]

1
Yeni başlayanlar olarak soru, sıralamayı endekse ve isme göre birleştirebilir misiniz? Örneğin data <- data[c(1,3,"Var1", 2)]?
Bram Vanroy

6
@BramVanroy nope, vektörler sadece bir tipte veri içerebileceğinden c(1,3,"Var1", 2)okunacaktır c("1","3","Var1", "2"), bu nedenle tipler mevcut en genel tipe yükseltilir. "1", "3" vb. Karakter adlarına sahip sütun olmadığından "tanımlanmamış sütunlar" elde edersiniz. list(1,3,"Var1", 2)değerleri tür tanıtımı olmadan tutar, ancak listyukarıdaki bağlamda a kullanamazsınız .
Terry Brown

1
mtcars[c(1,3,2)]Alt küme neden çalışıyor? Yanlış boyutlar veya benzerleri ile ilgili bir hata beklerdim ... Olmamalı mıydı mtcars[,c(1,3,2)]?
landroni


106

Alt küme işlevini de kullanabilirsiniz:

data <- subset(data, select=c(3,2,1))

Diğer yanıtlarda olduğu gibi [] operatörünü daha iyi kullanmalısınız, ancak tek bir komutta bir alt küme ve bir sütun yeniden sıralama işlemi yapabileceğinizi bilmek yararlı olabilir.

Güncelleme:

Dplyr paketinden select işlevini de kullanabilirsiniz:

data = data %>% select(Time, out, In, Files)

Verimlilik konusunda emin değilim, ancak dplyr'in sözdizimi sayesinde, özellikle çok fazla sütununuz varsa bu çözüm daha esnek olmalıdır. Örneğin, aşağıdakiler mtcars veri kümesinin sütunlarını ters sırada yeniden sıralayacaktır:

mtcars %>% select(carb:mpg)

Ve aşağıdakiler yalnızca bazı sütunları yeniden sıralar ve diğerlerini atar:

mtcars %>% select(mpg:disp, hp, wt, gear:qsec, starts_with('carb'))

Dplyr's select sözdizimi hakkında daha fazla bilgi edinin .


5
Kullanmamanız için bazı nedenler var, bu soruyasubset() bakın .
MERose

2
Teşekkür ederim. Her halükarda artık alt küme yerine dplyr paketinden select işlevini kullanacağım.
dalloliogm

87
Sol tarafa birkaç sütun getirmek ve diğerlerini düşürmek istemediğinizde, everything()özellikle harika buluyorum ; mtcars %>% select(wt, gear, everything())
guyabel

2
Sütunları sağa / sona yeniden düzenlemek için everything () select_helper işlevini kullanmanın başka bir yolu. stackoverflow.com/a/44353144/4663008 github.com/tidyverse/dplyr/issues/2838 Bazı sütunları sağa, diğerleri sola taşımak için 2 select () kullanmanız gerekecek gibi görünüyor.
Arthur Yip

1
yeni fonksiyon dplyr :: relocate tam olarak bunun içindir. aşağıdaki H 1'in cevabına bakınız
Arthur Yip

39

Bahsedildiği gibi bu yorumun bir yeniden sipariş sütunlar için standart önerileri data.framesütun bir şey var, özellikle genel hantal ve hataya açık bulunmaktadır.

Bu işlev sütunları konuma göre yeniden düzenlemenizi sağlar: bir değişken adı ve istenen konumu belirtin ve diğer sütunlar için endişelenmeyin.

##arrange df vars by position
##'vars' must be a named vector, e.g. c("var.name"=1)
arrange.vars <- function(data, vars){
    ##stop if not a data.frame (but should work for matrices as well)
    stopifnot(is.data.frame(data))

    ##sort out inputs
    data.nms <- names(data)
    var.nr <- length(data.nms)
    var.nms <- names(vars)
    var.pos <- vars
    ##sanity checks
    stopifnot( !any(duplicated(var.nms)), 
               !any(duplicated(var.pos)) )
    stopifnot( is.character(var.nms), 
               is.numeric(var.pos) )
    stopifnot( all(var.nms %in% data.nms) )
    stopifnot( all(var.pos > 0), 
               all(var.pos <= var.nr) )

    ##prepare output
    out.vec <- character(var.nr)
    out.vec[var.pos] <- var.nms
    out.vec[-var.pos] <- data.nms[ !(data.nms %in% var.nms) ]
    stopifnot( length(out.vec)==var.nr )

    ##re-arrange vars by position
    data <- data[ , out.vec]
    return(data)
}

Artık OP'nin isteği şu kadar basit hale geliyor:

table <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5))
table
##  Time In Out Files
##1    1  2   3     4
##2    2  3   4     5

arrange.vars(table, c("Out"=2))
##  Time Out In Files
##1    1   3  2     4
##2    2   4  3     5

Ek olarak takas Timeve Filessütunlar yapmak için şunları yapabilirsiniz:

arrange.vars(table, c("Out"=2, "Files"=1, "Time"=4))
##  Files Out In Time
##1     4   3  2    1
##2     5   4  3    2

Çok güzel bir işlev. Kişisel paketime bu işlevin değiştirilmiş bir sürümünü ekledim .
Deleet

1
Bu gerçekten yararlı - gerçekten geniş bir
tibble'ın sonundan

Vay canına, bunu seviyorum.
OfTheAzureSky

37

Bir dplyrçözüm ( tidyversepaket setinin bir parçası ) aşağıdakileri kullanmaktır select:

select(table, "Time", "Out", "In", "Files") 

# or

select(table, Time, Out, In, Files)

2
Benim için en iyi seçenek. Yüklemek zorunda kalsam bile, en açık ihtimal bu.
Garini

15
Tidyverse (aslında dplyr) da öne Türler değişkeni taşımak için örneğin sütun grupları seçmek için seçeneği vardır: select(iris, Species, everything()). Ayrıca tırnak işaretleri gerekli değildir.
Paul Rougieux

3
everything()PaulRougieux'un yorumunda yer almadığı sürece, açıkça belirtilmeyen tüm sütunları bırakacağını not etmek önemlidir
divibisan

dplyr'nin groupdeğişkenleri de yeniden düzenleyeceğinden, bunu bir zincirde kullanırken dikkat edin.
David Tonhofer

26

Belki de, istediğiniz sütun sırasının azalan alfabetik sırada sütun adlarının olması bir tesadüf olabilir. Durum böyle olduğu için şunları yapabilirsiniz:

df<-df[,order(colnames(df),decreasing=TRUE)]

Çok sütunlu büyük dosyalarım olduğunda kullanıyorum.


!! WARNING !! data.tableTARGETint vektörüne dönüşür : TARGET <- TARGET[ , order(colnames(TARGET), decreasing=TRUE)] bunu düzeltmek için: TARGET <- as.data.frame(TARGET) TARGET <- TARGET[ , order(colnames(TARGET), decreasing=TRUE)]
Zachary Ryan Smith


12

En yüksek puan alan üç cevap zayıf.

Veri çerçeveniz böyle görünüyorsa

df <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5))

> df
  Time In Out Files
1    1  2   3     4
2    2  3   4     5

o zaman kullanmak kötü bir çözüm

> df2[,c(1,3,2,4)]

İşi yapar, ancak girdinizdeki sütunların sırasına bir bağımlılık getirdiniz.

Bu kırılgan programlama tarzından kaçınılmalıdır.

Sütunların açıkça adlandırılması daha iyi bir çözümdür

data[,c("Time", "Out", "In", "Files")]

Ayrıca, kodunuzu daha genel bir ortamda yeniden kullanmak istiyorsanız,

out.column.name <- "Out"
in.column.name <- "In"
data[,c("Time", out.column.name, in.column.name, "Files")]

bu da oldukça güzel çünkü değişmezleri tamamen izole ediyor. Buna karşılık, eğer dplyrselect

data <- data %>% select(Time, out, In, Files)

kodunuzu daha sonra okuyacak olanları kendiniz de dahil olmak üzere, bir aldatma için kuruyorsunuz. Sütun adları, kodda olduğu gibi değişmez olarak kullanılır.


3

dplyrsürümü 1.0.0, relocate()sütunları kolayca yeniden sıralama işlevini içerir :

dat <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5))

library(dplyr) # from version 1.0.0 only

dat %>%
  relocate(Out, .before = In)

veya

dat %>%
  relocate(Out, .after = Time)

2
data.table::setcolorder(table, c("Out", "in", "files"))

pls işlevi setcolorderaldığınız kitaplığı belirtin .
Triamus

1

İyi iş gördüğüm tek kişi buradan .

 shuffle_columns <- function (invec, movecommand) {
      movecommand <- lapply(strsplit(strsplit(movecommand, ";")[[1]],
                                 ",|\\s+"), function(x) x[x != ""])
  movelist <- lapply(movecommand, function(x) {
    Where <- x[which(x %in% c("before", "after", "first",
                              "last")):length(x)]
    ToMove <- setdiff(x, Where)
    list(ToMove, Where)
  })
  myVec <- invec
  for (i in seq_along(movelist)) {
    temp <- setdiff(myVec, movelist[[i]][[1]])
    A <- movelist[[i]][[2]][1]
    if (A %in% c("before", "after")) {
      ba <- movelist[[i]][[2]][2]
      if (A == "before") {
        after <- match(ba, temp) - 1
      }
      else if (A == "after") {
        after <- match(ba, temp)
      }
    }
    else if (A == "first") {
      after <- 0
    }
    else if (A == "last") {
      after <- length(myVec)
    }
    myVec <- append(temp, values = movelist[[i]][[1]], after = after)
  }
  myVec
}

Bunun gibi kullanın:

new_df <- iris[shuffle_columns(names(iris), "Sepal.Width before Sepal.Length")]

Tıkır tıkır çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.