2012-06-19 3 views
2

Я совершенно новой для R и есть вопрос о петляхдвойная петля в R

В моей реальных данных там 7000 наблюдений в 80 странах с 15 секторами и 6 типов организаций, но здесь это упрощенный пример.

country <- c("a","a","a","a","a","a","b","b","b","b","b","b", 
      "c","c","c","c","c","c","d","d","d","d","d","d") 
sector <- c("a","a","a","b","c","c","a","b","b","b","c","c", 
      "b","b","b","b","c","c","a","a","b","b","c","c") 
organization <-c("a","b","c","c","b","a","a","b","b","c","b","b", 
       "c","a","a","b","b","c","c","b","a","a","b","c") 
budget <-c(2,4,3,5,9,7,5,4,3,6,1,2,4,5,6,1,5,3,4,2,3,5,4,6) 
table <- data.frame(country, sector, organization, budget) 

Что я хочу:

  1. Количество различных типов организаций в конкретной отрасли в конкретной стране.
  2. Процент от общего бюджета в секторе, предоставляемого различным организациям.

я сначала должен сделать подмножество выбрать только данные из страны «а» и сектор «а»

smalltable <-subset(table, (country == "a") & (sector == "a")) 

, а затем ответить на мой первый вопрос, сколько из каждого типа организации в сектор в стране

smalltable$count <- table(smalltable$organization) 

то мне нужно найти процент финансов

smalltable$percentage <- smalltable$budget/sum(smalltable$budget) 

тогда я использовал tapply

N <- tapply(smalltable$count, smalltable$organization, FUN=sum) 
financialshare <- tapply(smalltable$percentage, smalltable$organization, FUN=sum)  

и, наконец, в сочетании это:

total <- data.frame (smalltable$country,smalltable$sector,smalltable$organization, N,financialshare) 
total 

Это маленький столик, что я требую!

Но мне это нужно для всех моих 15 секторов и во всех 80 странах, поэтому мне нужна какая-то функция цикла, которая запускает цикл всех секторов и повторяет этот цикл для каждой страны. Мне нужно сделать эти таблицы максимально сжатыми, объединив всю информацию о 1 стране (так 15 секторов) в одну таблицу. Также необходимо удалить из таблиц нулевые значения, чтобы сэкономить место.

Как мне нужно продолжить?

+0

Да, но со всеми секторами в определенной стране в одном кадре. Таким образом, для образца я хотел бы иметь 4 специфичных для конкретной страны данных для передачи в excel – user1466195

ответ

3

Я дам data.table ответа

library(data.table) 
my_table=data.table(country, sector, organization, budget) 
by_org=my_table[, list(count=.N, budget=sum(budget)), 
        keyby=list(country, sector, organization)] 
total_budgets=my_table[, list(total_budget=sum(budget)), 
        keyby=list(country, sector)] 
joined_table= total_budgets[by_org] 
joined_table[,percentage:=budget/total_budget] 

EDIT от Матфея: В V1.8.1, используя := группой, объединения не требуется так это проще и быстрее, а столбец total_budget добавлен вправо, что является более естественным местом, чем там, где оно используется в v1.8.0:

DT = data.table(country, sector, organization, budget) 
ans = DT[, list(count=.N, budget=sum(budget)), 
      keyby=list(country, sector, organization)] 
ans[, total_budget:=sum(budget), by=list(country,sector)] 
ans[, percentage:=budget/total_budget] 

Результат (с использованием V1.8.1):

country sector organization count budget total_budget percentage 
1:  a  a   a  1  2   9 0.2222222 
2:  a  a   b  1  4   9 0.4444444 
3:  a  a   c  1  3   9 0.3333333 
4:  a  b   c  1  5   5 1.0000000 
5:  a  c   a  1  7   16 0.4375000 
6:  a  c   b  1  9   16 0.5625000 
7:  b  a   a  1  5   5 1.0000000 
8:  b  b   b  2  7   13 0.5384615 
9:  b  b   c  1  6   13 0.4615385 
10:  b  c   b  2  3   3 1.0000000 
11:  c  b   a  2  11   16 0.6875000 
12:  c  b   b  1  1   16 0.0625000 
13:  c  b   c  1  4   16 0.2500000 
14:  c  c   b  1  5   8 0.6250000 
15:  c  c   c  1  3   8 0.3750000 
16:  d  a   b  1  2   6 0.3333333 
17:  d  a   c  1  4   6 0.6666667 
18:  d  b   a  2  8   8 1.0000000 
19:  d  c   b  1  4   10 0.4000000 
20:  d  c   c  1  6   10 0.6000000 

Две вещи здесь отметить: первый Ваш вопрос немного расплывчато и противоречивы, как к тому, что вы на самом деле хотите, насколько это рассчитывает и суммы идут, но, надеюсь, мой отрывок достаточно ясен, насколько я могу сделать расчеты.

Во-вторых, он не является идиоматическим в R, чтобы пройти через большое количество наблюдений, поскольку это имеет тенденцию быть медленным. Большинство людей, которые запрограммировали R на некоторое время, имеют тенденцию использовать векторные операции, plyr, data.table или другие подобные пакеты.

Но быть завершена, конструкция петли следующим образом:

for (item in list) 
{ 
    ... 
} 

перебрать общие индексы ...

for (i in 1:length(object)) 
{ 
    ... 
} 
+0

в стране A и секторе A существует только одна организация типа A, но в вашем списке отображается число 3 – user1466195

+0

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

+0

отлично, спасибо – user1466195

2
library(plyr) 
ddply(table,.(country,sector), transform,count=as.vector(table(budget)),percentage=budget/sum(budget)) 

дает

country sector organization budget count percentage 
1  a  a   a  2  1 0.2222222 
2  a  a   b  4  1 0.4444444 
3  a  a   c  3  1 0.3333333 
4  a  b   c  5  1 1.0000000 
5  a  c   b  9  1 0.5625000 
6  a  c   a  7  1 0.4375000 
7  b  a   a  5  1 1.0000000 
8  b  b   b  4  1 0.3076923 
9  b  b   b  3  1 0.2307692 
10  b  b   c  6  1 0.4615385 
11  b  c   b  1  1 0.3333333 
12  b  c   b  2  1 0.6666667 
13  c  b   c  4  1 0.2500000 
14  c  b   a  5  1 0.3125000 
15  c  b   a  6  1 0.3750000 
16  c  b   b  1  1 0.0625000 
17  c  c   b  5  1 0.6250000 
18  c  c   c  3  1 0.3750000 
19  d  a   c  4  1 0.6666667 
20  d  a   b  2  1 0.3333333 
21  d  b   a  3  1 0.3750000 
22  d  b   a  5  1 0.6250000 
23  d  c   b  4  1 0.4000000 
24  d  c   c  6  1 0.6000000 
+0

Спасибо за это, но процент не должен быть для каждой записи, но для каждого типа организации. Поэтому в строках 11-12 и 21-22 тип организации «a» отображается дважды для одной и той же страны и сектора, и это не должно быть так. Их нужно суммировать, чтобы сформировать одну группу. Затем бюджеты также суммируются, а процент сравнивает организации типа «a» с типами «b» и «c». Это также позволило бы выполнить подсчет, который будет выше одного. – user1466195

1

Вы установить это идеально подходит для использования plyr. Под этим я подразумеваю, что у вас есть процесс, который (почти) работает на одном подмножестве, который возвращает именно то, что вы хотите для этого подмножества, и теперь вам нужно просто перебрать все возможные подмножества. Я переписал ваш код, чтобы сделать его более плотным и обойти возможные недостатки. organization s.

library("plyr") 

ddply(table, .(country, sector), function(smalltable) { 
    smalltable <- ddply(smalltable, .(organization), summarise, 
         count=length(budget), budget=sum(budget)) 
    smalltable$percentage <- smalltable$budget/sum(smalltable$budget) 
    smalltable 
}) 

который дает

country sector organization count budget percentage 
1  a  a   a  1  2 0.2222222 
2  a  a   b  1  4 0.4444444 
3  a  a   c  1  3 0.3333333 
4  a  b   c  1  5 1.0000000 
5  a  c   a  1  7 0.4375000 
6  a  c   b  1  9 0.5625000 
7  b  a   a  1  5 1.0000000 
8  b  b   b  2  7 0.5384615 
9  b  b   c  1  6 0.4615385 
10  b  c   b  2  3 1.0000000 
11  c  b   a  2  11 0.6875000 
12  c  b   b  1  1 0.0625000 
13  c  b   c  1  4 0.2500000 
14  c  c   b  1  5 0.6250000 
15  c  c   c  1  3 0.3750000 
16  d  a   b  1  2 0.3333333 
17  d  a   c  1  4 0.6666667 
18  d  b   a  2  8 1.0000000 
19  d  c   b  1  4 0.4000000 
20  d  c   c  1  6 0.6000000 

Обратите внимание, что table не хорошее имя для переменной, так как это также имя базовой функции.

+0

Вложенные 'ddply' в пределах другого' ddply' могут быть довольно медленными с увеличением размера данных, iiuc. –

+0

@MatthewDowle Это может быть, но с 7000 записей, внешняя группировка 1200 и внутренняя группировка 6, это должно быть разумным. Если это не так, то подход 'data.table' лучше. –

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