データフレームの列を並べ替える方法を教えてください。


311

この入力をどのように変更しますか(シーケンス:時間、入力、出力、ファイル):

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

この出力(シーケンス:時間、出力、入力、ファイル)に?

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

これがダミーのRデータです。

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)またとして知られている?'['
ヨリスMeys

3
ヨリスの示唆@に加えて、手動読みセクション2.7及び「Rへの入門」のセクション5をお試しください:cran.r-project.org/doc/manuals/R-intro.html
ギャビン・シンプソン

3
1つの追加の問題:すべての回答には列の完全なリストが必要です。それ以外の場合、サブセットになります。最初の列として順序付けするためにいくつかの列のみをリストし、他のすべての列も保持したい場合はどうなりますか?
000andy8484 2016年

回答:


341

データフレームには、4つの列がありますdf[,c(1,2,3,4)]。最初のコンマはすべての行を保持することを意味し、1,2,3,4は列を参照することに注意してください。

上記の質問のように順序を変更するには、 df2[,c(1,3,2,4)]

このファイルをcsvとして出力したい場合は、 write.csv(df2, file="somedf.csv")


35
列の数が限られている場合はこれで問題ありませんが、たとえば50列の場合、すべての列番号または名前を入力するのに時間がかかりすぎます。より速い解決策は何でしょうか?
Herman Toothrot 2013

54
@ user4050:その場合、「:」構文を使用できます(例:df [、c(1,3,2,4,5:50)]。
dalloliogm 14

1
列を開始時にidcolsに配置するには:idcols <-c( "name"、 "id2"、 "start"、 "duration"); cols <-c(idcols、names(cts)[-which(names(cts)%in%idcols)]); df <-df [cols]
kasterma

13
@ user4050:df[,c(1,3,2,4:ncol(df))]列の数がわからない場合にも使用できます。
arekolek 2016年

1
dput(colnames(df))を使用することもできます。これは、列名をR文字形式で出力します。その後、名前を並べ替えることができます。
クリス・

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

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

1
初心者としての質問ですが、インデックスと名前による順序付けを組み合わせることができますか?例えばdata <- data[c(1,3,"Var1", 2)]
Bram Vanroy、2014

6
@BramVanroyいいえ、ベクトルは1つのタイプのデータのみを含むことができるため、タイプは存在する最も一般的なタイプに昇格さc(1,3,"Var1", 2)れるc("1","3","Var1", "2")ため、読み取られます。「1」、「3」などの文字名を持つ列がないため、「未定義の列」が表示されます。 list(1,3,"Var1", 2)型の昇格なしで値を保持しますlistが、上記のコンテキストではa を使用できません。
Terry Brown

1
mtcars[c(1,3,2)]サブセット化が機能するのはなぜですか?不正確な寸法などに関連するエラーが発生すると予想していましたが、そうではありmtcars[,c(1,3,2)]ませんか?
landroni

data.framesは、最初の注文アイテムとして列を含む、内部のリストです
petermeissner 2015年

106

サブセット関数を使用することもできます。

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

他の回答と同様に[]演算子を使用することをお勧めしますが、単一のコマンドでサブセットと列の並べ替え操作を実行できることを知っておくと便利です。

更新:

dplyrパッケージの選択機能を使用することもできます。

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

効率についてはわかりませんが、dplyrの構文のおかげで、特に多数の列がある場合、このソリューションはより柔軟になります。たとえば、次はmtcarsデータセットの列を逆の順序で並べ替えます。

mtcars %>% select(carb:mpg)

そして、以下は一部の列のみを並べ替え、他は破棄します:

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

dplyrの選択構文の詳細をご覧ください。


5
使用しない理由はいくつかあります。この質問をsubset()参照してください。
MERose 2014年

2
ありがとうございました。いずれの場合も、サブセットではなく、dplyrパッケージの選択関数を使用します。
dalloliogm 2014年

87
いくつかの列を左側に持ってきて、他の列を落とさないようにしたい場合は、everything()特に素晴らしいと思います。 mtcars %>% select(wt, gear, everything())
guyabel

2
以下は、everything()select_helper関数を使用して列を右/末尾に再配置する別の方法です。 stackoverflow.com/a/44353144/4663008 github.com/tidyverse/dplyr/issues/2838 2つのselect()を使用して一部の列を右端に移動し、他の列を左端に移動する必要があるようです。
Arthur Yip 2017年

1
新しい関数dplyr :: relocateは、まさにこのためのものです。以下のH 1の回答を参照してください
アーサー・イップ

39

このコメントで述べたようにdata.frame、特に列が多い場合、aの列を並べ替える標準的な提案は、一般に扱いにくく、エラーが発生しやすくなります。

この関数を使用すると、列を位置で再配置できます。変数名と目的の位置を指定し、他の列については気にしないでください。

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

これでOPのリクエストは次のように単純になります。

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

さらに交換TimeしてFiles列を作成するには、次のようにします。

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

とても素敵な機能。この関数の修正版を個人用パッケージに追加しました。
2016

1
これは本当に便利です-私はほんの始まりに本当に広いtibbleの端から1列を移動したいとき、私に多くの時間を節約するために起こっている
Mrmoleje

うわー、私はこれが大好きです。
OfTheAzureSky

37

dplyr溶液(一部のtidyverseパッケージセット)を使用することですselect

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

# or

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

2
私にとって最良の選択肢です。私がそれをインストールしなければならなかったとしても、それは明らかに最も明確な可能性です。
Garini、

15
Tidyverse(実際にはdplyr)には、列のグループを選択するオプションもあります。たとえば、Species変数を前に移動しますselect(iris, Species, everything())。また、引用符は必要ありません。
ポールルージュ

3
これはeverything()、PaulRougieuxのコメント
divibisan

dplyrさんはgroupまた、チェーンのそれを使用する際に気をつけ、変数を並べ替えます。
David Tonhofer

26

たぶん、あなたが望む列の順序が偶然に降順の列名を持っているのは偶然でしょう。それはあなたがすることができるケースだからです:

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

多くの列を含む大きなファイルがある場合に使用します。


!! WARNING !! data.tableターンTARGETint型のベクターには:TARGET <- TARGET[ , order(colnames(TARGET), decreasing=TRUE)] 修正すること: TARGET <- as.data.frame(TARGET) TARGET <- TARGET[ , order(colnames(TARGET), decreasing=TRUE)]
ザカリー・ライアンスミス


12

3 トップクラスの 答えは弱点を持っています。

データフレームが次のようになっている場合

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

その後、それは使用するには貧弱なソリューションです

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

これは機能しますが、入力の列の順序に依存するようになりました。

このような脆弱なプログラミングのスタイルは避けてください。

列の明示的な命名はより良い解決策です

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

さらに、より一般的な設定でコードを再利用する場合は、簡単に

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

リテラルを完全に分離するので、これも非常に便利です。対照的に、dplyrのselect

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

次に、あなた自身を含めて、後であなたのコードを読む人を少し欺くために設定します。列名がリテラルとして使用されているため、コードに表示されていません。


3

dplyrバージョンに1.0.0は、relocate()列を簡単に並べ替える機能が含まれています。

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)

または

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


1

私がよく見たのはここからだけです。

 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
}

次のように使用します。

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

魅力のように機能します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.