2016-07-06 2 views
1

Обратите внимание, что в соответствии с требованиями комментариев этот вопрос был пересмотрен.Вывод процентилей путем фильтрации кадра данных

Рассмотрим следующий пример:

df <- data.frame(FILTER = rep(1:10, each = 10), VALUE = 1:100) 

Я хотел бы, для каждого значения FILTER, создать кадр данных, который содержит 1, 2, ..., 99-й процентили VALUE. Конечный продукт должен быть

PERCENTILE df_1 df_2 ... df_10 1 [first percentiles] 2 [second percentiles]

и т.д., где df_i основан на FILTER == i.

Обратите внимание, что FILTER, хотя он содержит цифры, на самом деле категоричен.

так, как я делал это с помощью dplyr:

nums <- 1:10 
library(dplyr) 
for (i in nums){ 
df_temp <- filter(df, FILTER == i)$VALUE 
assign(paste0("df_", i), quantile(df_temp, probs = (1:99)/100)) 
} 

, а затем я бы cbind этим (с 1:99 в первой колонке), но я предпочел бы не вводить каждый df имя. Я рассмотрел использование цикла для имен этих фреймов данных, но это будет связано с использованием eval(parse()).

+6

Вероятно, 'mget' и' do.call', но, конечно, проблема _real_ здесь заключается в том, что у вас нет всех 'df_1, df_2' и т. Д. В начале списка. – joran

+0

Чтобы получить наилучший ответ, не могли бы вы рассказать нам, как вы создали эти data.frames? Не подробно, но вы использовали цикл для чтения в csvs, используя 'assign'? –

+0

@ sebastian-c В принципе - я не уверен, что это имеет отношение к проблеме; Я предполагаю, что это не так - я должен фильтровать на основе 'i' из фрейма данных, сгенерированного' sqlQuery() '. По очевидным причинам я не могу публиковать эти данные на этом веб-сайте. Кадры данных, имена которых содержат 'i', представляют собой все dfs, содержащие процентили отфильтрованного кадра данных. Все они имеют одинаковое количество строк и имеют только один столбец, как в этом примере, и я хотел бы «cbind» их использовать цикл. – Clarinetist

ответ

1

Вот основной набросок, возможно, более плавного подхода. Я не включил ни одного аспекта желаемого вывода, но модификация должна быть довольно простой.

df <- data.frame(FILTER = rep(1:10, each = 10), VALUE = 1:100) 
df_s <- lapply(split(df,df$FILTER), 
          FUN = function(x) quantile(x$VALUE,probs = c(0.25,0.5,0.75))) 
out <- do.call(cbind,df_s) 
colnames(out) <- paste0("df_",colnames(out)) 

> out 
    df_1 df_2 df_3 df_4 df_5 df_6 df_7 df_8 df_9 df_10 
25% 3.25 13.25 23.25 33.25 43.25 53.25 63.25 73.25 83.25 93.25 
50% 5.50 15.50 25.50 35.50 45.50 55.50 65.50 75.50 85.50 95.50 
75% 7.75 17.75 27.75 37.75 47.75 57.75 67.75 77.75 87.75 97.75 

Я сделал это всего за 3 квантиля, чтобы все было просто, но оно очевидно распространяется. После этого вы можете добавить столбец 1:99.

+0

Я ценю вашу помощь по этому вопросу! Спасибо, и я не могу поверить, что до сих пор не знал о 'split' или' do.call'! :) – Clarinetist

0

Как насчет использования get?

df <- data.frame(1:10) 

for (i in nums) { 

    df <- cbind(df, get(paste0("df_", i))) 

} 

# get rid of first useless column 
df <- df[, -1] 

# get names 
names(df) <- paste0("df_", nums) 
df 
+1

Я понимаю причину не рекомендовать его, но опять-таки, его вопрос носит литеральный характер: «Я хотел бы привязать их, используя петлю». – Choubi

+0

Обратите внимание, что в соответствии с вашими комментариями я пересмотрел свой вопрос. – Clarinetist

1

Предлагаю вам использовать list.

list_of_dfs <- list() 
nums <- 1:10 
for (i in nums){ 
    list_of_dfs[[i]] <- nums*i 
} 

df <- data.frame(list_of_dfs[[1]]) 
df <- do.call("cbind",args=list(df,list_of_dfs)) 
colnames(df) <- paste0("df_",1:10) 

Вы получите результат, который вы хотите:

df_1 df_2 df_3 df_4 df_5 df_6 df_7 df_8 df_9 df_10 
1  1 2 3 4 5 6 7 8 9 10 
2  2 4 6 8 10 12 14 16 18 20 
3  3 6 9 12 15 18 21 24 27 30 
4  4 8 12 16 20 24 28 32 36 40 
5  5 10 15 20 25 30 35 40 45 50 
6  6 12 18 24 30 36 42 48 54 60 
7  7 14 21 28 35 42 49 56 63 70 
8  8 16 24 32 40 48 56 64 72 80 
9  9 18 27 36 45 54 63 72 81 90 
10 10 20 30 40 50 60 70 80 90 100 
+0

Обратите внимание, что в соответствии с вашими комментариями я пересмотрел свой вопрос. – Clarinetist

+0

Спасибо за предложение: я заменил второй цикл на do.call. Однако как бы вы назначили list_of_dfs, используя lapply? – Anton

+1

'lapply (1:10, function (i) nums * i)' должен работать. – Choubi

Смежные вопросы