Кросс-табулирование истинных значений только в R - PullRequest
1 голос
/ 01 августа 2011

У меня есть датафрейм "dataAll" и несколько переменных (A, B), я хочу таблицу типа

   A   >10    >20     >30

B

>1

>10

>100

Для этого я закодировал как

с (dataAll, таблица (A = A> 10, B = B> 1)), что дает мне

         A
               FALSE    TRUE
B

        FALSE  220357   4798

        TRUE  596618 210080

Итак, здесь значение 210080 должно идти в первую ячейку в верхней таблице

Я пробовал что-то подобное безуспешно

с (dataAll, таблица (A = A> c (10,20,30), B = B> c (1,10,100)))

и даже

с (dataAll, таблица (A = c (A> 10, A> 20, A> 30), B = c (B> 1, B> ​​10, B> 100)))

но безуспешно,

Я знаю, что должен быть способ сделать это ...

Ответы [ 3 ]

3 голосов
/ 02 августа 2011
A.categ <- cut(A, breaks = c(-Inf, 10, 20, 30, Inf), right=FALSE)
B.categ <- cut(B, breaks = c(-Inf, 1, 10, 100, Inf), right=FALSE)
table(A.categ, B.categ)

Хитрость с cut заключается в том, чтобы не забыть установить right = FALSE, так как большинство людей ожидают, что это сработает. Фактически, когда Фрэнк Харрелл сделал свою версию cut2 для Hmisc, он установил ее в качестве опции по умолчанию.

Когда вы делаете это с примером, созданным Томми, вы получаете

> A.categ <- cut(d$A, breaks = c(-Inf, 10, 20, 30, Inf), right=FALSE)
>     B.categ <- cut(d$B, breaks = c(-Inf, 1, 10, 100, Inf), right=FALSE)
>     table(A.categ, B.categ)
           B.categ
A.categ     [-Inf,1) [1,10) [10,100) [100, Inf)
  [-Inf,10)        0      1        1          9
  [10,20)          0      2        3          2
  [20,30)          0      5        4          1
  [30, Inf)        0     17       11         44

Не каждый понимает соглашение об открытии / закрытии, поэтому иногда вам нужно пойти и переработать labels факторизованной переменной, которую вы сконструировали с помощью cut, чтобы менее математически склонный клиент мог сопоставить ее со своими соглашениями. Вы используете функцию factor и задаете аргумент labels (и НЕ указываете аргумент levels, иначе вы «сломаете переменную»)

> A.categ <- factor(A.categ, labels=c(" Less than 1", "1-9.9", "10-99.9" , "100+") )
>     table(A.categ, B.categ)
              B.categ
A.categ        [-Inf,1) [1,10) [10,100) [100, Inf)
   Less than 1        0      1        1          9
  1-9.9               0      2        3          2
  10-99.9             0      5        4          1
  100+                0     17       11         44
2 голосов
/ 01 августа 2011

Вот небольшое решение на основе vapply. Предполагается, что требуется общее количество для каждой ячейки (например, A> 20 и B> 100), а не количество для (A> 20 и A <30) & (B> 100 и B <1000). </p>

# Create some data
set.seed(42)
n <- 100;
dataAll <- data.frame(A=runif(n, 1,100), B=10^runif(n, 0, 4))

# And some break points    
a <- 1:10*10 # 10, 20 etc...
b <- 10^(0:4) # 1, 10, 100, 1000


f <- function(A, a, B, b) {
    structure(t(vapply(b, function(bb) {
    vapply(a, function(aa, A) sum(A > aa), 1, A[B > bb])    
    }, a)), dimnames=list(B=b, A=a))
}

f(dataAll$A, a, dataAll$B, b)

Что дает следующую таблицу:

       A
B       10 20 30 40 50 60 70 80 90 100
  1     89 82 72 63 55 46 34 23 16   0
  10    65 60 55 47 41 34 26 18 12   0
  100   47 45 44 39 34 28 21 14 10   0
  1000  20 19 18 17 16 12  8  5  5   0
  10000  0  0  0  0  0  0  0  0  0   0

Суть всего этого состоит в том, чтобы подсчитать ИСТИННЫЕ значения для одного a условия sum(A > aa), а затем сделать это для всех a условий с вызовом vapply.

vapply(a, function(aa, A) sum(A > aa)    

Затем сделайте это снова для каждого b условия и добавьте несколько dimnames к (транспонированному) результату.

2 голосов
/ 01 августа 2011

попробуйте функцию вырезания.

?cut

работает с перерывами, как вы хотите.

cut(x,breaks,labels,...)


 table(cut(A[which(B<1)],breaks=c(0,10,20,30)))


 table(cut(A[which(B>1)],breaks=c(0,10,20,30)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...