डेटा फ़्रेम में कोई भी पुन: क्रमबद्ध कॉलम कैसे होता है?


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

यहाँ डमी आर डेटा है:

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)के रूप में भी जाना जाता है?'['
जोरिस मेय्स

3
@ जॉरिस के सुझाव के अलावा, "एक परिचय से आर" मैनुअल के खंड 2.7 और खंड 5 को पढ़ने का प्रयास करें: क्रैन .r
गेविन सिम्पसन

3
एक अतिरिक्त समस्या: सभी उत्तरों में स्तंभों की पूरी सूची की आवश्यकता होती है, अन्यथा वे परिणामहीन हो जाते हैं। क्या होगा यदि हम केवल पहले के रूप में आदेश दिए जाने वाले कुछ स्तंभों को सूचीबद्ध करना चाहते हैं, लेकिन अन्य सभी को भी बनाए रखना चाहते हैं?
000 कैंडी8484

जवाबों:


341

आपके डेटाफ्रेम में चार कॉलम हैं df[,c(1,2,3,4)]। ध्यान दें कि पहले अल्पविराम का मतलब सभी पंक्तियों को रखना है, और 1,2,3,4 कॉलम को संदर्भित करता है।

उपरोक्त प्रश्न के रूप में क्रम बदलने के लिए df2[,c(1,3,2,4)]

यदि आप इस फ़ाइल को सीएसवी के रूप में आउटपुट करना चाहते हैं, तो करें write.csv(df2, file="somedf.csv")


35
जब आपके पास सीमित संख्या में कॉलम होते हैं तो यह ठीक है, लेकिन क्या होगा यदि आपके पास उदाहरण के लिए 50 कॉलम हैं, तो सभी कॉलम नंबर या नाम टाइप करने में बहुत अधिक समय लगेगा। जल्दी हल क्या होगा?
हरमन टूथ्रोट

53
@ user4050: उस स्थिति में आप ":" सिंटैक्स, उदा df [, c (1,3,2,4,5: 50)] का उपयोग कर सकते हैं।
dalloliogm

1
कॉलम को शुरू में मूर्तियों में रखने के लिए: idcols <- c ("name", "id2", "start", "period"); cols <- c (idcols, names (cts) [- जो (नाम (cts)%% idcols] में)); df <- df [कर्नल]
kasterma

13
@ user4050: आप यह भी उपयोग कर सकते हैं df[,c(1,3,2,4:ncol(df))]जब आपको नहीं पता कि कितने कॉलम हैं।
इस्कॉलेक

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)]?
ब्रैम वनरॉय

6
@BramVanroy c(1,3,"Var1", 2)को नहीं पढ़ा जाएगा , c("1","3","Var1", "2")क्योंकि वैक्टर में केवल एक ही प्रकार का डेटा हो सकता है, इसलिए प्रकारों को सबसे सामान्य प्रकार में बढ़ावा दिया जाता है। क्योंकि चरित्र नाम "1", "3" आदि के साथ कोई कॉलम नहीं हैं , इसलिए आपको "अपरिभाषित कॉलम" मिलेंगे। list(1,3,"Var1", 2)टाइप प्रमोशन के बिना मान रखता है, लेकिन आप listउपरोक्त संदर्भ में उपयोग नहीं कर सकते ।
टेरी ब्राउन

1
mtcars[c(1,3,2)]सबसेट काम क्यों करता है ? मुझे गलत आयामों या समान से संबंधित त्रुटि की उम्मीद होगी ... क्या यह नहीं होना चाहिए mtcars[,c(1,3,2)]?
लैंड्रोनी

data.frames पहले क्रम के आइटम के रूप में कॉलम के साथ हुड के नीचे सूचीबद्ध हैं
पेटीएमनर

106

आप सब्मिट फ़ंक्शन का भी उपयोग कर सकते हैं:

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

आपको अन्य उत्तरों के रूप में [] ऑपरेटर का बेहतर उपयोग करना चाहिए, लेकिन यह जानना उपयोगी हो सकता है कि आप एक कमांड में एक सबसेट और एक कॉलम रीऑर्डर ऑपरेशन कर सकते हैं।

अपडेट करें:

आप dplyr पैकेज से चुनिंदा फ़ंक्शन का उपयोग कर सकते हैं:

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

मैं दक्षता के बारे में निश्चित नहीं हूं, लेकिन डुप्लिकेट के सिंटैक्स के लिए धन्यवाद यह समाधान अधिक लचीला होना चाहिए, खासकर यदि आपके पास बहुत सारे कॉलम हैं। उदाहरण के लिए, निम्नलिखित विपरीत क्रम में mtcars डेटासेट के कॉलम को फिर से व्यवस्थित करेगा:

mtcars %>% select(carb:mpg)

और निम्नलिखित केवल कुछ कॉलमों को फिर से चलाएंगे, और दूसरों को छोड़ देंगे:

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

बारे में अधिक पढ़ें dplyr के चयन वाक्य रचना


5
उपयोग नहीं करने के कुछ कारण हैं subset(), इस प्रश्न को देखें ।
23

2
धन्यवाद। किसी भी मामले में मैं अब सब्मिट के बजाय dplyr पैकेज से चुनिंदा फ़ंक्शन का उपयोग करूंगा।
डैलोलीम

87
जब आप बाएं हाथ की ओर कुछ कॉलम लाना चाहते हैं और दूसरों को नहीं छोड़ना चाहते हैं, तो मुझे everything()विशेष रूप से भयानक लगता है ; mtcars %>% select(wt, gear, everything())
मेनाबेल

2
स्तंभों को दाईं / छोर पर पुनर्व्यवस्थित करने के लिए सब कुछ () select_helper फ़ंक्शन का उपयोग करने का एक और तरीका है। stackoverflow.com/a/44353144/4663008 github.com/tidyverse/dplyr/issues/2838 आपको लगता है कि आपको 2 कॉलम का उपयोग करना होगा (कुछ स्तंभों को दाईं ओर ले जाने के लिए और दूसरे को बाईं ओर ले जाने के लिए)।
आर्थर यिप

1
नया फंक्शन dplyr :: रिलोकेट बिल्कुल इसके लिए है। नीचे एच 1 का जवाब देखें
आर्थर यिप

39

जैसा कि इस टिप्पणी में उल्लेख किया गया है , स्तंभों को फिर से आदेश देने के लिए मानक सुझाव data.frameआम तौर पर बोझिल और त्रुटि वाले हैं, खासकर यदि आपके पास बहुत सारे कॉलम हैं।

यह फ़ंक्शन कॉलम को स्थिति से फिर से व्यवस्थित करने की अनुमति देता है: एक चर नाम और वांछित स्थिति निर्दिष्ट करें, और अन्य कॉलम के बारे में चिंता न करें।

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

अब ओपी का अनुरोध इस तरह सरल हो गया है:

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

बहुत अच्छा समारोह। मैंने अपने व्यक्तिगत पैकेज में इस फ़ंक्शन का एक संशोधित संस्करण जोड़ा ।
देलेत

1
यह वास्तव में उपयोगी है - यह मुझे बहुत समय बचाने जा रहा है जब मैं सिर्फ एक स्तंभ को वास्तव में चौड़े टिबेबल के अंत से शुरुआत तक ले जाना चाहता हूं
Mrmoleje

वाह, मुझे यह पसंद है।
TheAzureSky

37

एक dplyrसमाधान ( tidyverseपैकेज सेट का हिस्सा ) का उपयोग करना है select:

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

# or

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

2
मेरे लिए सबसे अच्छा विकल्प। यहां तक ​​कि अगर मुझे इसे स्थापित करना था, तो यह स्पष्ट रूप से सबसे स्पष्ट संभावना है।
गरिमा

15
Tidyverse (वास्तव में dplyr) में स्तंभों के समूहों का चयन करने का विकल्प भी है, उदाहरण के लिए प्रजाति चर को सामने ले जाने के लिए select(iris, Species, everything()):। यह भी ध्यान दें कि उद्धरणों की आवश्यकता नहीं है।
पॉल रौजीक्स

3
यह नोट करना महत्वपूर्ण है कि यह उन सभी स्तंभों को छोड़ देगा जो स्पष्ट रूप से निर्दिष्ट नहीं किए जाते हैं जब तक कि आप everything()पॉल राउजी की टिप्पणी में शामिल नहीं होते हैं
divibisan

dplyrकी groupभी चर को पुनर्व्यवस्थित होगा, इसलिए जब एक श्रृंखला में है कि का उपयोग कर देखना।
डेविड टोनहोफर

26

हो सकता है कि यह एक संयोग हो कि आप जो कॉलम ऑर्डर चाहते हैं, वह कॉलम के नामों को अवरोही वर्णमाला क्रम में होता है। चूँकि आप ऐसा कर सकते हैं।

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

जब मैं कई कॉलम वाली बड़ी फाइल रखता हूं तो यही उपयोग करता हूं।


!! WARNING !! data.tableTARGETएक सदिश वेक्टर में बदल जाता है : TARGET <- TARGET[ , order(colnames(TARGET), decreasing=TRUE)] इसे ठीक करने के लिए: TARGET <- as.data.frame(TARGET) TARGET <- TARGET[ , order(colnames(TARGET), decreasing=TRUE)]
Zachary रयान स्मिथ


12

तीन टॉप रेटेड जवाब एक कमजोरी है।

यदि आपका डेटाफ्रेम ऐसा दिखता है

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")]

एक जादू की तरह काम करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.