2013-08-14 20 views
62

Chciałbym zamówić ramkę danych na podstawie różnych kolumn, jedna na turę. Mam wektor znaków z odpowiednimi nazwami kolumn, na których powinno się opierać order:

parameter <- c("market_value_LOCAL", "ep", "book_price", "sales_price", "dividend_yield", 
       "beta", "TOTAL_RATING_SCORE", "ENVIRONMENT", "SOCIAL", "GOVERNANCE") 

pragnę pętli ciągu nazwisk w parameter i dynamicznie wybrać kolumnę być wykorzystane do order moje dane:

Q1_R1000_parameter <- Q1_R1000[order(Q1_R1000$parameter[X]), ] 

gdzie X jest 1:10 (ponieważ mam 10 pozycji w parameter).


aby mój przykład powtarzalne, należy rozważyć dane ustawione mtcars i kilka nazw zmiennych przechowywanych w postaci wektorowej cols. Kiedy próbuję wybrać zmienną z mtcars stosując dynamiczną podzbiór cols, w podobny sposób jak powyżej (Q1_R1000$parameter[X]), kolumna nie jest zaznaczone:

cols <- c("cyl", "am") 
mtcars$cols[1] 
# NULL 

Odpowiedz

102

nie można zrobić tego rodzaju podzbiorów z $ W kodzie źródłowym (R/src/main/subset.c) stwierdza:

/* Operator podzbioru $ .
Musimy być pewni, że oceniamy tylko pierwszy argument.
Drugi będzie symbolem, który musi zostać dopasowany, a nie oceniany.
*/

Drugi argument? Co?! Musisz zdać sobie sprawę, że $, podobnie jak wszystko inne w R, (w tym na przykład (, +, ^ itp.) Jest funkcją, która pobiera argumenty i jest oceniana. df$V1 może być przepisany jako

`$`(df , V1) 

czy rzeczywiście

`$`(df , "V1") 

Ale ...

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

... na przykład nigdy nie będzie działać, ani też cokolwiek innego, należy najpierw ocenić w drugim argumencie. Możesz przesyłać tylko ciąg, który jest oceniany.

Zamiast tego użyj [ (lub [[, jeśli chcesz wyodrębnić tylko jedną kolumnę jako wektor).

Na przykład

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] 

Można wykonać kolejność bez pętli, używając do.call do skonstruowania wywołanie order. Oto powtarzalne przykład poniżej:

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

Jeśli dobrze rozumiem, masz wektor zawierający zmienną Nazwy i chciałbym zapętlić każdą nazwę i posortować ramkę danych przez nich. Jeśli tak, ten przykład powinien zilustrować rozwiązanie dla Ciebie. Główny problem w twoim (pełny przykład nie jest kompletny, więc nie jestem pewien, czego jeszcze możesz brakować) jest to, że powinien on być order(Q1_R1000[,parameter[X]]) zamiast order(Q1_R1000$parameter[X]), ponieważ parametr jest obiektem zewnętrznym, który zawiera nazwę zmiennej przeciwnej do .. bezpośredni kolumna ramki danych (które, gdy $ byłoby właściwe)

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 
0
Q1_R1000[do.call(order, Q1_R1000[parameter]), ] 
1

Korzystanie dplyr zapewnia łatwy składnia do sortowania danych ramki

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

To może być przydatne do korzystania z wersji NSE, aby umożliwić dynamiczne budowanie rodzaju lista

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

Co NSE tu na myśli? – discipulus

+1

@discipulus ocena niestandardowa; do pracy z opóźnionymi wyrażeniami dynamicznie buduje kod za pomocą łańcuchów zamiast twardego kodowania. Zobacz tutaj, aby uzyskać więcej informacji: https://cran.r-project.org/web/packages/lazyeval/vignettes/lazyeval.html – manotheshark

-1

miał podobne problemy z powodu pewnych plików CSV, które miały różne nazwy dla SAM e kolumna.
Było to rozwiązanie:

Napisałem funkcja zwraca pierwszą prawidłową nazwę kolumny na liście, a następnie wykorzystywane że ...

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