2012-02-09 2 views
2

Как и в моем вопросе вчера на reshaping matrices in R, я сейчас пытаюсь изменить кадры данных, чтобы я мог векторизовать свою функцию. В приведенном ниже коде основной функцией является scorecard. Он принимает в фрейме данных subset.loans и subset.collateral. Я задаюсь вопросом, могу ли я изменить два кадра loans и collaterals, которые оба выглядят следующим образом:Векторизация списка операций с списками в R

LOANS    COLLATERAL   
id | value  id | value type    
----------  -------------------    
1  200  1  600  a 
2 4390  1  899  b    
2  860  2  190  d    
2 9750  3 4930  e    
3  600  3  300  a    
:  :  :  :  : 

В это:

id | loans    collateral 
----------------------------- 
1 c(200)   data.frame(a=c(600,899), b=('a','b')) 
2 c(4390,860,9750) data.frame(a=c(190), b=c('d')) 
3 c(600)   data.frame(a=c(4930,300), b=c('e','a')) 

Моя надежда состоит в том, что если я сделаю это, я могу потом используйте одну из функций *apply - или что-нибудь из инструментария plyr - просто примените функцию scorecard по всему предмету. Если есть лучший/более простой способ, пожалуйста, укажите его! Код, который я сейчас использую (с богом забытом for цикла) следующим образом:

# An Nx2 data frame of loans (ID, amount) 
loans <- read.table(...) 

# An Mx4 data frame of collaterals to loans (ID, type, value, lien) 
collateral <- read.table(...) 

# One person (ID) can have >1 loan and >1 collateral, so first just 
# find all unique IDs 
loans.ID.unique = unique(loans$ID) 

# Run an analysis on each ID grouping: 
for(n in 1:length(loans.ID.unique)) { 

    # ...all loans for that ID... 
    subset.loans  <- loans$loans[ 
         which(
          loans$scorecard_id == loans.ID.unique[n])] 

    # ...all collateral for that ID... 
    subset.collateral <- collateral[ 
         which(
          collateral$scorecard_id == loans.ID.unique[n]), 
         c('type','value','lien')] 

    # Output scores for each ID 
    scores[n,1] <- loans.ID.unique[n] 
    scores[n,c(2,3)] <- scorecard(loans=subset.loans, 
           collateral=subset.collateral, 
} 

Спасибо!

+1

Вы должны представить себя в 'plyr' пакет. Шаг 1: используйте 'merge' для объединения ваших данных в один файл data.frame. Шаг 2: используйте 'plyr :: ddply', чтобы выполнить вашу работу за один шаг. – Andrie

+0

@andrie - я загрузил его, но еще не использовал его. (Я только начал использовать R около месяца назад, поэтому у меня есть кое-что, на что нужно обратить внимание.) Если это действительно так просто, как вы говорите, это просто потрясающе. – eykanal

+0

Когда вы начинаете изучать R, у вас всегда есть несколько вещей, на которые нужно смотреть, и чем лучше я получаю с R, я нахожу, что список вещей, на которые нужно смотреть, растет экспоненциально :) –

ответ

3

1) Нет структуры данных. Было бы необычно создать такую ​​структуру в R. Предложите вам просто взять то, что вам нужно на лету. Здесь Loans и Collateral - ваши два кадра входных данных, а loans и collateral - это части для текущего id обрабатываемых. Заменить двойной хэш строки функции ниже с вашим собственным кодом:

ids <- union(Loans$id, Collateral$id) 
do.call("rbind", lapply(ids, function(id) { 
    loans <- Loans[Loans$id == id, "value"] 
    collateral <- Collateral[Collateral$id == id, -1] 
    c(id = id, score = sum(loans) - sum(collateral$value)) ## 
})) 

ADDED:

2) Матрица. С другой стороны, если мы действительно хотим создать такую ​​структуру, это может быть сделано так:

ids <- union(Loans$id, Collateral$id) 
m <- cbind(id = ids, 
    loans = lapply(ids, function(id) Loans[Loans$id == id, "value"]), 
    collateral = lapply(ids, function(id) Collateral[Collateral$id == id, -1]) 
) 

do.call("rbind", lapply(1:nrow(m), function(i) with(m[i,], 
    c(id = id, score = sum(loans) - sum(collateral$value)) 
))) 

3) Фрейм данных. Мы могли бы попеременно представить структуру в виде кадра данных, d <- as.date.frame(m) или ниже, который является почти то же самое:

d <- data.frame(id = ids, 
    loans = I(lapply(ids, function(id) Loans[Loans$id == id, "value"])), 
    collateral = I(lapply(ids, function(id) Collateral[Collateral$id == id, -1])) 
) 
do.call("rbind", lapply(1:nrow(m), function(i) with(d, 
    c(id = id[[i]], score = sum(loans[[i]]) - sum(collateral[[i]]$value)) 
))) 

EDIT: Упрощенный код, который строит m.

ADDED: представление кадра данных.

+0

Очень интересно. Я действительно пытался создать тип данных 'struct' MATLAB, но это выглядит намного чище. – eykanal

+0

Я добавил пример, показывающий, как создать такую ​​структуру, чтобы увидеть, как она выглядит на всякий случай. –

0

Вам вообще не нужно преобразовывать свои данные. Фактически, преобразование, которое вы ищете, невозможно, потому что вы не можете иметь data.frame внутри data.frame. Вместо этого попробуйте использовать lapply в вашей системе показателей.

# Read in data 
loans=data.frame(id=c(1,2,2,2,3),value=c(200,4390,860,9750,600)) 
col=data.frame(id=c(1,1,2,3,3),value=c(600,899,190,4930,300),type=c('a','b','d','e','a')) 

# Load in scorecard function 
scorecard = function(subset.loans,subset.collateral) { 
    # Do something other than this 
    list(subset.loans,subset.collateral) 
} 

# Use lapply 
lapply(unique(loans$id), 
function (x) scorecard(loans[loans$id==x,] , col[col$id==x,c('type','value')]) 
) 

Если вы хотите превратить ваши данные, как вы упомянули, вы могли бы сделать что-то подобное с этим:

loans.agg=aggregate(loans$value,by=list(loans$id),c) 
names(loans.agg)=c('id','loans') 

col.agg.val=aggregate(col$value,by=list(col$id),c) 
names(col.agg.val)=c('id','collateral') 

col.agg.type=aggregate(col$type,by=list(col$id),c) 
names(col.agg.type)=c('id','type') 

# What you probably want 
merge(merge(loans.agg,col.agg.val),col.agg.type) 
Смежные вопросы