$ और वर्ण मान का उपयोग करके डेटा फ्रेम कॉलम को गतिशील रूप से चुनें


122

मेरे पास विभिन्न कॉलम नामों का वेक्टर है और मैं उस कॉलम को डेटा.फ्रेम से निकालने के लिए उनमें से प्रत्येक पर लूप करने में सक्षम होना चाहता हूं। उदाहरण के लिए, mtcarsएक चरित्र वेक्टर में संग्रहीत डेटा सेट और कुछ चर नामों पर विचार करें cols। जब मैं एक चर का चयन करने की कोशिश करता हूंmtcarscols इन कार्यों के एक गतिशील सबसेट का उपयोग करने

cols <- c("mpg", "cyl", "am")
col <- cols[1]
col
# [1] "mpg"

mtcars$col
# NULL
mtcars$cols[1]
# NULL

मैं इन मूल्यों को वापस कैसे ला सकता हूं

mtcars$mpg

इसके अलावा मैं colsकिसी प्रकार के लूप में मूल्यों को प्राप्त करने के लिए सभी स्तंभों पर कैसे लूप कर सकता हूं ।

for(x in seq_along(cols)) {
   value <- mtcars[ order(mtcars$cols[x]), ]
}

जवाबों:


183

आप उस तरह की सबसेट नहीं कर सकते $। स्रोत कोड में ( R/src/main/subset.c) यह बताता है:

/ * $ सबसेट ऑपरेटर।
हमें केवल पहले तर्क का मूल्यांकन करने के लिए सुनिश्चित होना चाहिए।
दूसरा एक प्रतीक होगा जिसका मिलान किया जाना चाहिए, मूल्यांकन नहीं किया जाना चाहिए।
* /

दूसरा तर्क? क्या?! आप को एहसास है कि है $आर में सब कुछ की तरह, (उदाहरण के लिए सहित (, +, ^आदि) एक समारोह, कि तर्क लेता है और मूल्यांकन किया जाता है है। df$V1के रूप में फिर से लिखा जा सकता है

`$`(df , V1)

या वास्तव में

`$`(df , "V1")

परंतु...

`$`(df , paste0("V1") )

... उदाहरण के लिए, कभी काम नहीं करेगा, और न ही कुछ और होगा जिसका पहले दूसरे तर्क में मूल्यांकन किया जाना चाहिए। आप केवल एक स्ट्रिंग पास कर सकते हैं जो कभी नहीं होती है मूल्यांकन किया जाता है।

इसके बजाय उपयोग करें [(या [[यदि आप वेक्टर के रूप में केवल एक कॉलम निकालना चाहते हैं)।

उदाहरण के लिए,

var <- "mpg"
#Doesn't work
mtcars$var
#These both work, but note that what they return is different
# the first is a vector, the second is a data.frame
mtcars[[var]]
mtcars[var]

आप do.callकॉल का निर्माण करने के लिए , लूप के बिना ऑर्डर कर सकते हैं order। यहाँ एक प्रतिलिपि प्रस्तुत करने योग्य उदाहरण नीचे दिया गया है:

#  set seed for reproducibility
set.seed(123)
df <- data.frame( col1 = sample(5,10,repl=T) , col2 = sample(5,10,repl=T) , col3 = sample(5,10,repl=T) )

#  We want to sort by 'col3' then by 'col1'
sort_list <- c("col3","col1")

#  Use 'do.call' to call order. Seccond argument in do.call is a list of arguments
#  to pass to the first argument, in this case 'order'.
#  Since  a data.frame is really a list, we just subset the data.frame
#  according to the columns we want to sort in, in that order
df[ do.call( order , df[ , match( sort_list , names(df) ) ]  ) , ]

   col1 col2 col3
10    3    5    1
9     3    2    2
7     3    2    3
8     5    1    3
6     1    5    4
3     3    4    4
2     4    3    4
5     5    1    4
1     2    5    5
4     5    3    5

क्या यह स्थिति वर्षों में बदल गई है?
डुनोइस

4

अगर मैं सही तरीके से समझूं, तो आपके पास एक वैरिएबल नाम होगा जिसमें प्रत्येक नाम के माध्यम से लूप होगा और उनके द्वारा आपके डेटा फ्रेम को क्रमबद्ध किया जाएगा। यदि हां, तो इस उदाहरण को आपके लिए एक समाधान बताना चाहिए। आप में प्राथमिक मुद्दा (पूर्ण उदाहरण पूरा नहीं है इसलिए मुझे यकीन नहीं है कि आप और क्या गायब हो सकते हैं) यह है कि इसके order(Q1_R1000[,parameter[X]])बजाय होना चाहिए order(Q1_R1000$parameter[X]), क्योंकि पैरामीटर एक बाहरी वस्तु है जिसमें एक सीधा स्तंभ के विपरीत एक चर नाम शामिल है आपके डेटा फ्रेम (जो $उचित होगा)।

set.seed(1)
dat <- data.frame(var1=round(rnorm(10)),
                   var2=round(rnorm(10)),
                   var3=round(rnorm(10)))
param <- paste0("var",1:3)
dat
#   var1 var2 var3
#1    -1    2    1
#2     0    0    1
#3    -1   -1    0
#4     2   -2   -2
#5     0    1    1
#6    -1    0    0
#7     0    0    0
#8     1    1   -1
#9     1    1    0
#10    0    1    0

for(p in rev(param)){
   dat <- dat[order(dat[,p]),]
 }
dat
#   var1 var2 var3
#3    -1   -1    0
#6    -1    0    0
#1    -1    2    1
#7     0    0    0
#2     0    0    1
#10    0    1    0
#5     0    1    1
#8     1    1   -1
#9     1    1    0
#4     2   -2   -2

4

डेटा फ़्रेम को सॉर्ट करने के लिए dplyr का उपयोग करना एक आसान वाक्यविन्यास प्रदान करता है

library(dplyr)
mtcars %>% arrange(gear, desc(mpg))

यह एनएसई संस्करण का उपयोग करने के लिए उपयोगी हो सकता है जैसा कि गतिशील रूप से सॉर्ट सूची बनाने की अनुमति देने के लिए यहां दिखाया गया है

sort_list <- c("gear", "desc(mpg)")
mtcars %>% arrange_(.dots = sort_list)

NSE का यहां क्या मतलब है?
शिष्य

1
@discipulus गैर-मानक मूल्यांकन; यह हार्ड-कोडिंग के बजाय स्ट्रिंग के साथ कोड को गतिशील रूप से बनाने के लिए विलंबित अभिव्यक्तियों के साथ काम करने के लिए है। अधिक जानकारी के लिए यहां देखें: cran.r-project.org/web/packages/lazyeval/vignettes/…
manotheshark

1

एक अन्य उपाय #get का उपयोग करना है:

> cols <- c("cyl", "am")
> get(cols[1], mtcars)
 [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4

0

कुछ CSV फ़ाइलों के कारण समान समस्या थी, जिसमें एक ही कॉलम के विभिन्न नाम थे।
यह था हल:

मैंने एक सूची में पहला वैध कॉलम नाम वापस करने के लिए एक फ़ंक्शन लिखा, फिर उसका उपयोग किया ...

# Return the string name of the first name in names that is a column name in tbl
# else null
ChooseCorrectColumnName <- function(tbl, names) {
for(n in names) {
    if (n %in% colnames(tbl)) {
        return(n)
    }
}
return(null)
}

then...

cptcodefieldname = ChooseCorrectColumnName(file, c("CPT", "CPT.Code"))
icdcodefieldname = ChooseCorrectColumnName(file, c("ICD.10.CM.Code", "ICD10.Code"))

if (is.null(cptcodefieldname) || is.null(icdcodefieldname)) {
        print("Bad file column name")
}

# Here we use the hash table implementation where 
# we have a string key and list value so we need actual strings,
# not Factors
file[cptcodefieldname] = as.character(file[cptcodefieldname])
file[icdcodefieldname] = as.character(file[icdcodefieldname])
for (i in 1:length(file[cptcodefieldname])) {
    cpt_valid_icds[file[cptcodefieldname][i]] <<- unique(c(cpt_valid_icds[[file[cptcodefieldname][i]]], file[icdcodefieldname][i]))
}

0

यदि आप विशिष्ट नाम वाले कॉलम का चयन करना चाहते हैं तो बस करें

A=mtcars[,which(conames(mtcars)==cols[1])]
#and then
colnames(mtcars)[A]=cols[1]

आप इसे लूप में चला सकते हैं और साथ ही डायनामिक नाम जोड़ने के लिए उल्टा तरीका कर सकते हैं जैसे यदि A डेटा फ्रेम है और xyz को x नाम दिया जाना है तो मुझे यह पसंद है

A$tmp=xyz
colnames(A)[colnames(A)=="tmp"]=x

फिर से इसे लूप में भी जोड़ा जा सकता है


मुझे नहीं पता कि नकारात्मक वोट क्यों दिया गया है, लेकिन यह जटिल कार्यों को लिखने के बजाय काम करता है और आसान तरीका है
makarand kulkarni


-1

बहुत देर हो गई .. लेकिन मुझे लगता है कि मेरे पास जवाब है -

यहाँ मेरा नमूना अध्ययन है। डेटाफ़्रेम -

   >study.df
   study   sample       collection_dt other_column
   1 DS-111 ES768098 2019-01-21:04:00:30         <NA>
   2 DS-111 ES768099 2018-12-20:08:00:30   some_value
   3 DS-111 ES768100                <NA>   some_value

और तब -

> ## Selecting Columns in an Given order
> ## Create ColNames vector as per your Preference
> 
> selectCols <- c('study','collection_dt','sample')
> 
> ## Select data from Study.df with help of selection vector
> selectCols %>% select(.data=study.df,.)
   study       collection_dt   sample
1 DS-111 2019-01-21:04:00:30 ES768098
2 DS-111 2018-12-20:08:00:30 ES768099
3 DS-111                <NA> ES768100
> 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.