नामों से कई स्तंभों का नाम बदलें


84

किसी को यह पहले से ही पूछना चाहिए था, लेकिन मुझे कोई जवाब नहीं मिला। कहो मेरे पास:

x = data.frame(q=1,w=2,e=3, ...and many many columns...)  

स्तंभों के एक मनमाने उपसर्ग का नाम बदलने का सबसे सुंदर तरीका क्या है, जिसकी स्थिति मुझे आवश्यक रूप से कुछ अन्य मनमाने नामों में नहीं पता है?

जैसे कहते हैं कि मैं नाम बदलना चाहते हैं "q"और "e"में "A"और "B", क्या यह करने के लिए सबसे खूबसूरत कोड है?

जाहिर है, मैं एक लूप कर सकता हूं:

oldnames = c("q","e")
newnames = c("A","B")
for(i in 1:2) names(x)[names(x) == oldnames[i]] = newnames[i]

लेकिन मुझे आश्चर्य है कि क्या कोई बेहतर तरीका है? शायद संकुल में से कुछ का उपयोग कर? ( plyr::renameआदि)

जवाबों:


106

setnamesसे data.tableपैकेज पर काम करेंगे data.frameया data.tableरों

library(data.table)
d <- data.frame(a=1:2,b=2:3,d=4:5)
setnames(d, old = c('a','d'), new = c('anew','dnew'))
d


 #   anew b dnew
 # 1    1 2    4
 # 2    2 3    5

ध्यान दें कि परिवर्तन संदर्भ द्वारा किए गए हैं, इसलिए कोई भी प्रतिलिपि नहीं की जा रही है (डेटा के लिए भी! वर्कफ़्लो!)


1
यहां देर से आगमन के लिए - जोएल के जवाब पर भी एक नज़र डालें, जिसमें मौजूदा स्तंभों के लिए जाँच शामिल है यदि आपके पास नाम परिवर्तनों की एक सूची है जो सभी मौजूद नहीं हो सकती है जैसेold = c("a", "d", "e")
माइक

1
मुझे आश्चर्य है, क्या यह काम करता है अगर आप केवल उन सभी के बजाय एक सबसेट / कुछ स्तंभों का नाम बदलना चाहते हैं? इसलिए अगर मेरे पास दस कॉलमों का डेटा फ्रेम था और पहले नाम और _id_lastname को नामांकित करने के लिए _id_firstname का नाम बदलना चाहता था, लेकिन शेष आठ कॉलमों को अछूता छोड़ दें, क्या मैं ऐसा कर सकता हूं या मुझे सभी कॉलमों को सूचीबद्ध करना होगा?
मूसा

@MusTheDataGuy आप नए और पुराने नामों के सबसेट की आपूर्ति करते हैं, और यह काम करेगा।
16'18

@ मुझे किसी सबटेट के वैरिएबल नाम बदलने की जरूरत है जैसा @ मूस ने पूछा था। हालाँकि, ऊपर वाला कोड डेटा के सबसेट के लिए काम नहीं करता था। @ गोरखा का जवाब rename_at()एक सबसेट के परिवर्तनशील नामों के लिए काम करता है।
मेहमत यिलदिरिम

95

के साथ आप क्या करेंगे:

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)
    
df %>% rename(A = q, B = e)

#  A w B
#1 1 2 3

या यदि आप वैक्टर का उपयोग करना चाहते हैं, जैसा कि @ जेलेना-बायोइनफ द्वारा सुझाया गया है:

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)

oldnames = c("q","e")
newnames = c("A","B")

df %>% rename_at(vars(oldnames), ~ newnames)

#  A w B
#1 1 2 3

एलडी निकोलस ने सुझाव दिया कि एक परिवर्तन दिया rename_atजा रहा है rename_with:

df %>% 
  rename_with(~ newnames[which(oldnames == .x)], .cols = oldnames)

#  A w B
#1 1 2 3

2
उपयोगकर्ता ने पासिंग oldऔर newनाम के रूप में वैक्टर के बारे में पूछा , मुझे लगता है
जेलेनाlुकलिना

4
धन्यवाद @ जेलेना-बायोइनफ। मैंने आपके सुझाव को शामिल करने के लिए उत्तर में संशोधन किया।
गोरखा

क्या आप कृपया ~ (tilde) का अर्थ समझा सकते हैं और कहां ".x" का नाम rename_with उदाहरण से आता है?
पेटीज

rename_with.colsतर्क के रूप में दिए गए सभी स्तंभों का नाम बदलने के लिए फ़ंक्शन या सूत्र का उपयोग कर सकते हैं । उदाहरण के लिए rename_with(iris, toupper, starts_with("Petal"))के बराबर है rename_with(iris, ~ toupper(.x), starts_with("Petal"))
पॉल रौजीक्स

38

डेटाफ्रेम के लिए एक और समाधान जो बहुत बड़ा नहीं है (@thelatemail उत्तर पर निर्माण):

x <- data.frame(q=1,w=2,e=3)

> x
  q w e
1 1 2 3

colnames(x) <- c("A","w","B")

> x
  A w B
1 1 2 3

वैकल्पिक रूप से, आप भी उपयोग कर सकते हैं:

names(x) <- c("C","w","D")

> x
  C w D
1 1 2 3

इसके अलावा, आप स्तंभों के सबसेट का नाम भी बदल सकते हैं:

names(x)[2:3] <- c("E","F")

> x
  C E F
1 1 2 3

25

यहाँ सबसे कुशल तरीका है जिसमें मैंने purrr::set_names()और कुछ stringrपरिचालनों के संयोजन का उपयोग करके कई स्तंभों का नाम बदला है ।

library(tidyverse)

# Make a tibble with bad names
data <- tibble(
    `Bad NameS 1` = letters[1:10],
    `bAd NameS 2` = rnorm(10)
)

data 
# A tibble: 10 x 2
   `Bad NameS 1` `bAd NameS 2`
   <chr>                 <dbl>
 1 a                    -0.840
 2 b                    -1.56 
 3 c                    -0.625
 4 d                     0.506
 5 e                    -1.52 
 6 f                    -0.212
 7 g                    -1.50 
 8 h                    -1.53 
 9 i                     0.420
 10 j                     0.957

# Use purrr::set_names() with annonymous function of stringr operations
data %>%
    set_names(~ str_to_lower(.) %>%
                  str_replace_all(" ", "_") %>%
                  str_replace_all("bad", "good"))

# A tibble: 10 x 2
   good_names_1 good_names_2
   <chr>               <dbl>
 1 a                  -0.840
 2 b                  -1.56 
 3 c                  -0.625
 4 d                   0.506
 5 e                  -1.52 
 6 f                  -0.212
 7 g                  -1.50 
 8 h                  -1.53 
 9 i                   0.420
10 j                   0.957

6
यह उत्तर होना चाहिए, लेकिन क्या आपको पाइप में क्या ~और .तर्क देना चाहिए, इस पर विस्तार करना चाहिए set_names()
डेवआरजीपी

कुछ मामलों में, आपको स्पष्ट रूप से टाइप करने की आवश्यकता है purrr::set_names()
लेवी बागुले 20

1
@DaveRGP purrrफ़ंक्शन का उपयोग करते समय, टिल्ड का ~अर्थ है "प्रत्येक स्तंभ के लिए"। .एलएचएस = पाइप के बाएं हाथ की ओर के लिए dplyr वाक्य रचना, यानी वस्तु जो इस मामले में पहुंचाया जाता है, के संदर्भ में है data
एजिल बीन

टिल्ड ~एक सूत्र है। तुम भी एक समारोह कॉल का उपयोग करें और करने के लिए तर्क पारित कर सकते हैं ...के तर्क set_namesउदाहरण के लिए rlang::set_names(head(iris), paste0, "_hi")के बराबर है rlang::set_names(head(iris), ~ paste0(.x, "_hi"))
पॉल रौजीक्स

11

इसलिए मैं हाल ही में खुद इस में भाग गया, यदि आप सुनिश्चित नहीं हैं कि क्या कॉलम मौजूद हैं और केवल उन लोगों का नाम बदलना चाहते हैं:

existing <- match(oldNames,names(x))
names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]

6

@ उपयोगकर्ता 3114046 के उत्तर पर निर्माण:

x <- data.frame(q=1,w=2,e=3)
x
#  q w e
#1 1 2 3

names(x)[match(oldnames,names(x))] <- newnames

x
#  A w B
#1 1 2 3

यह xडेटासेट में कॉलम के एक विशिष्ट क्रम पर निर्भर नहीं होगा ।


1
मैंने आपके उत्तर को बदल दिया है, लेकिन मुझे अभी भी आश्चर्य है कि क्या ऐसा करने का एक और भी सुंदर तरीका है, विशेष रूप से विधियाँ जो कि नाम से बदले, स्थिति के अनुसार
क्यूहेल्थ

@qoheleth - यह नाम से बदल रहा है! यहाँ कोई इनपुट नहीं है जो एक स्थितिगत वेक्टर है जैसा matchकि ध्यान रखता है। आप जो सबसे अच्छा करने जा रहे हैं, वह शायद @ मेल का setnamesजवाब है।
Thelatemail

1
यह अभी भी स्थिति के अनुसार नाम बदलने की तरह है, क्योंकि आपने कहा था, भले ही मुझे स्पष्ट रूप से एक स्थिति वेक्टर निर्दिष्ट करने की आवश्यकता नहीं है, फिर matchभी एक स्थिति उन्मुख कमांड है। इस भावना में, मैंने @ user3114046 की उत्तर स्थिति के आधार पर भी (यहां तक ​​कि सोचा था कि %in%कमांड देखभाल करता है (या चीजों की कोशिश करता है))। बेशक, मुझे लगता है कि आप तर्क दे सकते हैं कि सभी कमांड पोजिशन ओरिएंटेड हैं जब हम निचले स्तर के तंत्र के लिए नीचे ड्रिल करते हैं .... लेकिन इसका मतलब यह नहीं है ... डेटाटेबल उत्तर महान है क्योंकि इसमें कोई कॉलिंग नहीं है nameआज्ञा देता है।
किओलेथ

4

यह सभी नामों में उन अक्षरों की सभी घटनाओं को बदल देगा:

 names(x) <- gsub("q", "A", gsub("e", "B", names(x) ) )

2
मुझे नहीं लगता कि यह नाम बदलने के उदाहरणों के एक जोड़े को प्राप्त करने के बाद यह विशेष रूप से सुरुचिपूर्ण है।
Thelatemail

मैं सिर्फ एक gsubfnउत्तर को कोड़ा मारने के लिए पर्याप्त नहीं हूं । शायद G.Grothendieck द्वारा आएगा। वह रेगेक्स-मिस्टर है।
IRTFM

4
names(x)[names(x) %in% c("q","e")]<-c("A","B")

2
बिलकुल नहीं, क्योंकि जैसा कि मैंने कहा, मुझे जरूरी नहीं कि स्तम्भों की स्थिति oldnamesज्ञात हो , आपका समाधान केवल तभी काम करता है जब उसे क्रमबद्ध किया जाता है ताकि i <j के लिए oldnames[i]पहले हो oldnames[j]
किओलेथ

2

आप नाम सेट प्राप्त कर सकते हैं, इसे एक सूची के रूप में सहेज सकते हैं, और फिर स्ट्रिंग पर अपना थोक नाम बदल सकते हैं। इसका एक अच्छा उदाहरण है जब आप किसी डेटासेट पर लंबे समय से व्यापक परिवर्तन कर रहे हैं:

names(labWide)
      Lab1    Lab10    Lab11    Lab12    Lab13    Lab14    Lab15    Lab16
1 35.75366 22.79493 30.32075 34.25637 30.66477 32.04059 24.46663 22.53063

nameVec <- names(labWide)
nameVec <- gsub("Lab","LabLat",nameVec)

names(labWide) <- nameVec
"LabLat1"  "LabLat10" "LabLat11" "LabLat12" "LabLat13" "LabLat14""LabLat15"    "LabLat16" " 

2

सिडेनोट, यदि आप सभी स्तंभ नामों में से एक स्ट्रिंग को संक्षिप्त करना चाहते हैं, तो आप बस इस सरल कोड का उपयोग कर सकते हैं।

colnames(df) <- paste("renamed_",colnames(df),sep="")

2

यदि तालिका में एक ही नाम के दो कॉलम हैं, तो कोड इस प्रकार है,

rename(df,newname=oldname.x,newname=oldname.y)

2

आप एक नामित वेक्टर का उपयोग कर सकते हैं।

बेस आर के साथ (शायद कुछ क्लंकी):

x = data.frame(q = 1, w = 2, e = 3) 

rename_vec <- c(q = "A", e = "B")

names(x) <- ifelse(is.na(rename_vec[names(x)]), names(x), rename_vec[names(x)])

x
#>   A w B
#> 1 1 2 3

या इसके dplyrसाथ एक विकल्प !!!:

library(dplyr)

rename_vec <- c(A = "q", B = "e") # the names are just the other way round than in the base R way!

x %>% rename(!!!rename_vec)
#>   A w B
#> 1 1 2 3

उत्तरार्द्ध काम करता है क्योंकि 'बिग-बैंग' ऑपरेटर !!!किसी सूची या वेक्टर के मूल्यांकन के लिए मजबूर कर रहा है।

?`!!`

!!! बलों-वस्तुओं की एक सूची का विभाजन। सूची के तत्वों को स्थान पर रखा गया है, जिसका अर्थ है कि वे प्रत्येक एक एकल तर्क बन जाते हैं।


यह कैसे काम करता है समझ में नहीं आता - !!!oldnamesरिटर्न c("A", "B")लेकिन जो तर्क रूपांतरण इस में c("A", "w", "B")??
एजाइल बीन

@AgileBean मुझे नहीं पता कि आपने कहां पाया है कि - पुराने नाम एक वेक्टर को लौटाएंगे। इसका उपयोग dplyr में कई तर्कों के गैर-मानक मूल्यांकन को बाध्य करने के लिए किया जाता है। देखते हैं ?`!!` Use `!!!` to add multiple arguments to a function. Its argument should evaluate to a list or vector: args <- list(1:3, na.rm = TRUE) ; quo(mean(!!!args))। मुझे लगता है कि मैं इस स्पष्टीकरण को उत्तर में जोड़ दूंगा। इसे लाने के लिए चीयर्स
tjebo

1

लॉट्स ऑफ सॉर्ट-ऑफ-आंसर, इसलिए मैंने सिर्फ फ़ंक्शन लिखा है ताकि आप कॉपी / पेस्ट कर सकें।

rename <- function(x, old_names, new_names) {
    stopifnot(length(old_names) == length(new_names))
    # pull out the names that are actually in x
    old_nms <- old_names[old_names %in% names(x)]
    new_nms <- new_names[old_names %in% names(x)]

    # call out the column names that don't exist
    not_nms <- setdiff(old_names, old_nms)
    if(length(not_nms) > 0) {
        msg <- paste(paste(not_nms, collapse = ", "), 
            "are not columns in the dataframe, so won't be renamed.")
        warning(msg)
    }

    # rename
    names(x)[names(x) %in% old_nms] <- new_nms
    x
}

 x = data.frame(q = 1, w = 2, e = 3)
 rename(x, c("q", "e"), c("Q", "E"))

   Q w E
 1 1 2 3

rename(x, c("q", "e"), c("Q", "E"))अब नाम बदलने के काम में नहीं लगता है?
sindri_baldur

0

यदि डेटा की एक पंक्ति में वे नाम हैं जिन्हें आप अपने लिए सभी कॉलमों को बदलना चाहते हैं

names(data) <- data[row,]

दिया गया dataआपका डेटाफ्रेम है और rowनए मानों वाली पंक्ति संख्या है।

फिर आप नामों वाली पंक्ति को हटा सकते हैं

data <- data[-row,]

0

यह वह फ़ंक्शन है जिसकी आपको आवश्यकता है: फिर x को एक नाम (X) में पास करें और यह उन सभी मानों का नाम बदल देगा जो दिखाई देते हैं और यदि यह नहीं है तो यह त्रुटि नहीं होगी

rename <-function(x){
  oldNames = c("a","b","c")
  newNames = c("d","e","f")
  existing <- match(oldNames,names(x))
  names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]
  return(x)
}

1
यह जोएलकाइपर के उत्तर के समान ही प्रतीत होता है , लेकिन फिर फ़ंक्शन के रूप में फिर से तैयार किया जाता है .....
जाप

0

कार्यों का उल्लेख dplyr::rename_withऔर rlang::set_namesपहले से ही कुछ जवाब हैं । इनके द्वारा अलग होते हैं। यह उत्तर स्तंभों का नाम बदलने के लिए फ़ंक्शंस और फ़ार्मुलों के उपयोग के बीच के अंतरों को दिखाता है।

rename_withdplyrपैकेज से .colsतर्क के रूप में दिए गए स्तंभों के चयन का नाम बदलने के लिए एक फ़ंक्शन या सूत्र का उपयोग कर सकते हैं । उदाहरण के लिए फ़ंक्शन नाम पास करना toupper:

library(dplyr)
rename_with(head(iris), toupper, starts_with("Petal"))

फार्मूला पास करने के बराबर है ~ toupper(.x):

rename_with(head(iris), ~ toupper(.x), starts_with("Petal"))

सभी स्तंभों का नाम बदलने के दौरान, आप set_namesrlang पैकेज से भी उपयोग कर सकते हैं । एक अलग उदाहरण बनाने के लिए, आइए paste0नाम बदलने के कार्य के रूप में उपयोग करें । pasteO2 तर्क लेता है, जिसके परिणामस्वरूप दूसरे तर्क को पारित करने के लिए अलग-अलग तरीके हैं जो कि हम एक फ़ंक्शन या सूत्र का उपयोग करते हैं।

rlang::set_names(head(iris), paste0, "_hi")
rlang::set_names(head(iris), ~ paste0(.x, "_hi"))

एक ही साथ प्राप्त किया जा सकता rename_withपहले तर्क के रूप में डेटा फ्रेम पारित करके .data, दूसरा तर्क के रूप में कार्य .fn, तीसरा तर्क के रूप में सभी स्तंभों .cols=everything()और चौथे तर्क के रूप में फ़ंक्शन पैरामीटर ...। वैकल्पिक रूप से आप दूसरे तर्क के रूप में दिए गए एक सूत्र में दूसरे, तीसरे और चौथे तर्क को रख सकते हैं।

rename_with(head(iris), paste0, everything(), "_hi")
rename_with(head(iris), ~ paste0(.x, "_hi"))

rename_withकेवल डेटा फ्रेम के साथ काम करता है। set_namesअधिक सामान्य है और वेक्टर नामकरण भी कर सकता है

rlang::set_names(1:4, c("a", "b", "c", "d"))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.