Вычисление числа чисел в подмножествах data.frame - PullRequest
3 голосов
/ 17 марта 2011

У меня есть кадр данных в R, который похож на следующее.На самом деле мой настоящий фрейм данных 'df' здесь намного больше, чем этот, но я действительно не хочу никого путать, поэтому я стараюсь максимально упростить вещи.

Итак, вот фрейм данных.

id <-c(1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3)   
a <-c(3,1,3,3,1,3,3,3,3,1,3,2,1,2,1,3,3,2,1,1,1,3,1,3,3,3,2,1,1,3)
b <-c(3,2,1,1,1,1,1,1,1,1,1,2,1,3,2,1,1,1,2,1,3,1,2,2,1,3,3,2,3,2)
c <-c(1,3,2,3,2,1,2,3,3,2,2,3,1,2,3,3,3,1,1,2,3,3,1,2,2,3,2,2,3,2)
d <-c(3,3,3,1,3,2,2,1,2,3,2,2,2,1,3,1,2,2,3,2,3,2,3,2,1,1,1,1,1,2)
e <-c(2,3,1,2,1,2,3,3,1,1,2,1,1,3,3,2,1,1,3,3,2,2,3,3,3,2,3,2,1,3)

df <-data.frame(id,a,b,c,d,e)
df

По сути, я хотел бы получить числа для каждого столбца (a, b, c, d, e) и для каждой группы идентификаторов (1,2,3) (дляэта последняя группа см. мой столбец "id").

Таким образом, для столбца 'a' и для номера идентификатора '1' (для последнего см. Столбец 'id') код будет выглядеть примерно так:

as.numeric(table(df[1:10,2]))

##The results are:
[1] 3 7

Просто краткообъясните мои результаты: в столбце «а» (и в отношении только тех записей, которые имеют номер «1» в столбце «id») можно сказать, что число «1» встречалось 3 раза, а число «3» - 7 раз.

Опять же, просто чтобы показать вам другой пример.Для столбца «a» и для номера идентификатора «2» (для последней группировки снова см. Столбец «id»):

as.numeric(table(df[11:20,2]))

##After running the codes the results are: 
[1] 4 3 3

Позвольте мне еще немного пояснить: в столбце «a» и касаемо только тех,наблюдения, которые имеют номер «2» в столбце «id»), мы можем сказать, что число «1» произошло 4 раза, число «2» произошло 3 раза и число «3» произошло 3 раза.

Так что эточто я хотел бы сделать.Вычисление вхождений чисел для каждого пользовательского подмножества (а затем сбор этих значений во фрейм данных).Я знаю, что это не сложная задача, но ПРОБЛЕМА заключается в том, что мне придется регулярно менять входной фрейм данных 'df', и, следовательно, как общее количество строк, так и столбцов может меняться со временем…

То, что я до сих пор делал, это то, что я разделил фрейм данных 'df' по столбцам, например:

for (z in (2:ncol(df))) assign(paste("df",z,sep="."),df[,z])

Таким образом, df.2 будет ссылаться на df $ a, df.3 будет равно df $b, df.4 будет равно df $ c и т. д. Но я действительно застрял сейчас и не знаю, как двигаться дальше ...

Существует ли правильный, "автоматический" способ решения этой проблемы?

Ответы [ 5 ]

5 голосов
/ 17 марта 2011

Как насчет -

> library(reshape)

> dftab <- table(melt(df,'id'))
> dftab
, , value = 1

   variable
id  a b c d e
  1 3 8 2 2 4
  2 4 6 3 2 4
  3 4 2 1 5 1

, , value = 2

   variable
id  a b c d e
  1 0 1 4 3 3
  2 3 3 3 6 2
  3 1 4 5 3 4

, , value = 3

   variable
id  a b c d e
  1 7 1 4 5 3
  2 3 1 4 2 4
  3 5 4 4 2 5

Таким образом, чтобы получить количество «3» в столбце «а» и группе «1» Вы могли бы просто сделать

> dftab[3,'a',1]
[1] 4
2 голосов
/ 17 марта 2011

Сочетание tapply и apply может создать нужные данные:

tapply(df$id,df$id,function(x) apply(df[id==x,-1],2,table))

Однако, когда в группе нет всех элементов, как в 1a, результатом будет список для этой группы id, а не красивая таблица (матрица).

$`1`
$`1`$a

1 3 
3 7 

$`1`$b

1 2 3 
8 1 1 

$`1`$c

1 2 3 
2 4 4 

$`1`$d

1 2 3 
2 3 5 

$`1`$e

1 2 3 
4 3 3 


$`2`
  a b c d e
1 4 6 3 2 4
2 3 3 3 6 2
3 3 1 4 2 4

$`3`
  a b c d e
1 4 2 1 5 1
2 1 4 5 3 4
3 5 4 4 2 5
0 голосов
/ 26 мая 2014

Вы не сказали, как вам нужны данные.Функция by может дать вам желаемый результат.

by(df, df$id, function(x) lapply(x[,-1], table))
0 голосов
/ 01 апреля 2014

Способ сделать это - использовать функцию aggregate, но вы должны добавить столбец к вашему фрейму данных

> df$freq <- 0
> aggregate(freq~a+id,df,length)
  a id freq
1 1  1    3
2 3  1    7
3 1  2    4
4 2  2    3
5 3  2    3
6 1  3    4
7 2  3    1
8 3  3    5

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

> frequency <- function(df,groups) {
+   relevant <- df[,groups]
+   relevant$freq <- 0
+   aggregate(freq~.,relevant,length)
+ }
> frequency(df,c("b","id"))
  b id freq
1 1  1    8
2 2  1    1
3 3  1    1
4 1  2    6
5 2  2    3
6 3  2    1
7 1  3    2
8 2  3    4
9 3  3    4
0 голосов
/ 17 марта 2011

Я уверен, что у кого-то будет более элегантное решение, чем это, но вы можете сделать это вместе с простой функцией и dlply из пакета plyr.

ColTables <- function(df) {
  counts <- list()
  for(a in names(df)[names(df) != "id"]) {
    counts[[a]] <- table(df[a])
  }
  return(counts)
}

results <- dlply(df, "id", ColTables)

Это вернет вам список - первым «слоем» списка будет переменная id; вторая table результаты для каждого столбца для этой переменной id. Например:

> results[['2']]['a']
$a

1 2 3 
4 3 3 

Для переменной id = 2, column = a, в соответствии с приведенным выше примером.

...