$ Ve bir karakter değeri kullanarak veri çerçevesi sütunlarını dinamik olarak seçin


122

Farklı sütun adlarından oluşan bir vektörüm var ve bir data.frame'den bu sütunu çıkarmak için her birinin üzerinde döngü yapabilmek istiyorum. Örneğin, veri kümesini mtcarsve bir karakter vektöründe depolanan bazı değişken adlarını düşünün cols. mtcarsDinamik alt kümesini kullanarak bir değişken seçmeye çalıştığımda cols, bunların nether

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

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

bunların aynı değerleri döndürmesini nasıl sağlayabilirim

mtcars$mpg

Dahası cols, değerleri bir tür döngüde elde etmek için tüm sütunlar arasında nasıl döngü yapabilirim .

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

Yanıtlar:


183

Bu tür bir alt küme ile yapamazsınız $. Kaynak kodunda ( R/src/main/subset.c) şunu belirtir:

/ * $ Alt küme operatörü.
Yalnızca ilk argümanı değerlendirdiğimizden emin olmalıyız.
İkincisi, eşleştirilmesi gereken, değerlendirilmemesi gereken bir sembol olacaktır.
* /

İkinci argüman? Ne?! Bunu gerçekleştirmek zorunda $Ar her şey gibi, (örneğin dahil (, +, ^argüman alır ve değerlendirilir bir fonksiyonudur vs). df$V1olarak yeniden yazılabilir

`$`(df , V1)

ya da gerçekten

`$`(df , "V1")

Fakat...

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

... örneğin asla işe yaramayacak, ilk önce ikinci argümanda değerlendirilmesi gereken başka hiçbir şey olmayacak. Asla olmayan bir dizeyi yalnızca değerlendirilmeyen .

Bunun yerine kullanın [(veya [[yalnızca tek bir sütunu vektör olarak çıkarmak istiyorsanız).

Örneğin,

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Çağrıyı oluşturmak için kullanarak döngüler olmadan sıralamayı gerçekleştirebilirsiniz order. Aşağıda tekrarlanabilir bir örnek verilmiştir:

#  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

O zamandan beri bu durum değişti mi?
Dunois

4

Doğru anladıysam, değişken adlarını içeren bir vektörünüz var ve her adda döngü yapmak ve veri çerçevenizi bunlara göre sıralamak istiyorsunuz. Öyleyse, bu örnek sizin için bir çözümü göstermelidir. Sizinki birincil sorun (tam örnek tam değil, bu yüzden başka ne eksik olabileceğinizden emin değilim) order(Q1_R1000[,parameter[X]])bunun yerine olması gerektiğidir order(Q1_R1000$parameter[X]), çünkü parametre, doğrudan bir sütunun aksine bir değişken adı içeren harici bir nesnedir veri çerçevenizin (hangisi $uygunsa).

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 kullanmak, veri çerçevelerini sıralamak için kolay bir sözdizimi sağlar

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

Sıralama listesinin dinamik olarak oluşturulmasına izin vermek için burada gösterildiği gibi NSE sürümünü kullanmak faydalı olabilir.

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

NSE burada ne anlama geliyor?
discipulus

1
@discipulus standart dışı değerlendirme; kodu sabit kodlama yerine dizelerle dinamik olarak oluşturmak için gecikmiş ifadelerle çalışmak içindir. Daha fazla bilgi için buraya bakın: cran.r-project.org/web/packages/lazyeval/vignettes/…
manotheshark

1

Diğer bir çözüm ise #get kullanmaktır:

> 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

Aynı sütun için çeşitli adlara sahip bazı CSV dosyalarından dolayı benzer sorun yaşandı.
Çözüm buydu:

Bir listedeki ilk geçerli sütun adını döndürmek için bir işlev yazdım, sonra bunu kullandım ...

# 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

belirli bir ada sahip bir sütun seçmek istiyorsanız,

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

Dinamik ad eklemek için döngü içinde ve tersi şekilde de çalıştırabilirsiniz, örneğin, A veri çerçevesi ve xyz, x olarak adlandırılacak sütunsa, bunu beğendim

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

yine bu döngüde eklenebilir


Neden olumsuz oy kullandığını bilmiyorum ama karmaşık fonksiyonlar yazmak yerine işe yarıyor ve kolay bir yol
makarand kulkarni


-1

çok geç .. ama sanırım cevabım var -

İşte örnek study.df veri çerçevem ​​-

   >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

Ve sonra -

> ## 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
> 
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.