2015-11-09 1 views
0

Мне нужно зациклиться на кадре данных и вычислить функции над переменной, которая зацикливается.R-ddply function over loop variable

Таблица Пример:

table<-data.frame(num1=seq(1,10,len=20), num2=seq(20,30,len=20), 
    char1=c(rep('a',10), rep('b',10)), 
    target=c(rep(1,10), rep(0,10))) 

создать список переменных:

nums<-colnames(table)[sapply(table, class)=='numeric'] 
nums<-nums[nums!='target'] 

И таблицу, я заселить:

planF<-data.frame(deciles=c(1), min=c(1), max=c(1), pos=c(1)) 
planF<-planF[-1,] 

и цикл:

library(plyr) 

for (i in 1:length(nums)){ 
table$deciles<-ntile(table[,nums[i]],5) 
plan<-ddply(table, 'deciles', summarize, min=min(nums[i]), 
     max=max(nums[i]),pos=sum(target)) 
planF<-rbind(planF,plan) 
} 

Мне нужно получить min и max переменной por каждый дециль. Но вместо этого я получаю:

deciles min max pos 
1  1 num1 num1 4 
2  2 num2 num2 4 
3  3 <NA> <NA> 2 
4  4 <NA> <NA> 0 
5  5 <NA> <NA> 0 
6  1 num1 num1 4 
7  2 num2 num2 4 
8  3 <NA> <NA> 2 
9  4 <NA> <NA> 0 
10  5 <NA> <NA> 0 

Для переменной num1 мне нужно, чтобы получить результат:

ddply(table, 'deciles', summarize, min=min(num1), 
     max=max(num1),pos=sum(target)) 


    deciles  min  max pos 
     1 5.736842 7.157895 0 
     2 7.631579 9.052632 0 
     3 1.000000 10.000000 2 
     4 1.947368 3.368421 4 
     5 3.842105 5.263158 4 

И ниже результата делать то же самое с num2.

Я понимаю, что мне нужно ввести переменную с помощью следующей формы:

num1

но код пишет

'num1'

Я попытался с:

min=min(as.name(nums[i])) 

Но я получить сообщение об ошибке:

Error in min(as.name(nums[i])) : 'type' (symbol) not valid argument

как я могу вычислить функцию над переменной, которая зацикливается?

+0

Трудно определить, что именно вы пытаетесь сделать. Можете ли вы объяснить это словами? – MJeffryes

+0

@MJeffryes: Привет, мне нужно получить min и max переменной por каждый decile. – GabyLP

+0

Было бы проще, если бы вы показали свой желаемый результат тоже. –

ответ

0

Я бы строго предпочитают использовать dplyr для этого, хотя есть некоторые уродства в обработке имен переменных строк в вызове summarize_ (обратите внимание на заднюю _):

library(lazyeval) 
library(dplyr) 

# create the data.frame 
dfX = data.frame(num1=seq(1,10,len=20), 
       num2=seq(20,30,len=20), 
       char1=c(rep('a',10), rep('b',10)), 
       target=c(rep(1,10), rep(0,10)) 
) 

# select the numeric columns 
numericCols = names(dfX)[sapply(dfX, is.numeric)] 
numericCols = setdiff(numericCols, "target") 

# cycle over numeric columns, creating summary data.frames 
liDFY = setNames(
    lapply(
    numericCols, function(x) { 
     # compute the quantiles 
     quantiles = quantile(dfX[[x]], probs = seq(0, 1, 0.2)) 

     # create quantile membership 
     dfX[["quantile_membership"]] = 
     findInterval(dfX[[x]], vec = quantiles, 
        rightmost.closed = TRUE, 
        all.inside = TRUE) 

     # summarize variables by decile 
     dfX %>% 
     group_by(quantile_membership) %>% 
     summarize_(min = interp(~ min(x_name), x_name = as.name(x)), 
        max = interp(~ max(x_name), x_name = as.name(x)), 
        mean = interp(~ mean(x_name), x_name = as.name(x))) 
    }), 
    numericCols 
) 

# inspect the output 
liDFY[[numericCols[1]]] 
+0

спасибо! 2 вопроса: Что делает findInterval? и как я могу ввести имя переменной (в каждой строке), чтобы знать, к каким переменным относятся? – GabyLP

+0

@GabyLP. 'FindInterval' использует квантили, вычисленные в строке выше, для каждого наблюдения (независимо от того, находится ли он в первом квантиле, втором квантиле и так далее), чтобы мы могли использовать эту информацию для группировки данных и вычисления min, макс и другие сводные статистические данные. – tchakravarty

+1

@GabyLP Вы можете просто добавить '%>% mutate (varname = x)'. – tchakravarty

1

Суть вашего вопроса для применения списка функций по методу split-apply-comb, так что вы можете сделать это в базе r.

## your data 
table<-data.frame(num1=seq(1,10,len=20), num2=seq(20,30,len=20), 
        char1=c(rep('a',10), rep('b',10)), 
        target=c(rep(1,10), rep(0,10))) 
nums<-colnames(table)[sapply(table, class)=='numeric'] 
nums<-nums[nums!='target'] 
table$deciles <- ntile(table[, nums[1]], 5) 

FUNS <- list(min = min, max = max, mean = mean) 

## split the variable num1 by deciles 
## apply each function to each piece 
x <- with(table, tapply(num1, deciles, function(x) 
    setNames(sapply(FUNS, function(y) y(x)), names(FUNS)))) 

## combine results 
do.call('rbind', x) 
#  min  max  mean 
# 1 1.000000 2.421053 1.710526 
# 2 2.894737 4.315789 3.605263 
# 3 4.789474 6.210526 5.500000 
# 4 6.684211 8.105263 7.394737 
# 5 8.578947 10.000000 9.289474 

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

f <- function(num, data = table) { 
    FUNS <- list(min = min, max = max, mean = mean) 

    x <- tapply(data[, num], data[, 'deciles'], function(x) 
    setNames(sapply(FUNS, function(y) y(x)), names(FUNS))) 

    cbind(deciles = as.numeric(names(x)), do.call('rbind', x)) 
} 

Таким образом, мы метод обобщен, поэтому он может использовать любой столбец, который у вас есть, с любыми данными, которые у вас есть.Вы можете назвать это для отдельных столбцов, как

f('num1') 
f('num2') 

Или использовать цикл, чтобы получить все сразу

lapply(c('num1','num2'), f) 

# [[1]] 
# deciles  min  max  mean 
# 1  1 1.000000 2.421053 1.710526 
# 2  2 2.894737 4.315789 3.605263 
# 3  3 4.789474 6.210526 5.500000 
# 4  4 6.684211 8.105263 7.394737 
# 5  5 8.578947 10.000000 9.289474 
# 
# [[2]] 
# deciles  min  max  mean 
# 1  1 20.00000 21.57895 20.78947 
# 2  2 22.10526 23.68421 22.89474 
# 3  3 24.21053 25.78947 25.00000 
# 4  4 26.31579 27.89474 27.10526 
# 5  5 28.42105 30.00000 29.21053 

Если вам не нравится lapply, вы можете Vectorize функцию, чтобы сделать его немного легче :

Vectorize(f, SIMPLIFY = FALSE)(c('num1', 'num2')) 

что вы чаще использовать, как это (SIMPLIFY = FALSE сохранить список структур)

v <- Vectorize(f, SIMPLIFY = FALSE) 
v(c('num1','num1')) 

# $num1 
# deciles  min  max  mean 
# 1  1 1.000000 2.421053 1.710526 
# 2  2 2.894737 4.315789 3.605263 
# 3  3 4.789474 6.210526 5.500000 
# 4  4 6.684211 8.105263 7.394737 
# 5  5 8.578947 10.000000 9.289474 
# 
# $num1 
# deciles  min  max  mean 
# 1  1 1.000000 2.421053 1.710526 
# 2  2 2.894737 4.315789 3.605263 
# 3  3 4.789474 6.210526 5.500000 
# 4  4 6.684211 8.105263 7.394737 
# 5  5 8.578947 10.000000 9.289474 

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

  • Нет связанных вопросов^_^