подсчитать количество частей строки по столбцам - PullRequest
4 голосов
/ 24 мая 2011

У меня есть такой текстовый файл:

V1 V2   V3
X  N    aaaaaabbbabab
C  T    ababaaabaaabb
V  H    babbbabaabbba

Что я хочу сделать, так это подсчитать, сколько a и сколько b содержится в столбце каждого V3.

Таким образом, результат будет выглядеть так:

   col1  col2 col3 .......  col13
a  2     2    2             1
b  1     1    1             2

Как это можно сделать?

Я попробовал функцию count вместе с подстрокой, но она не сработала.

Спасибо

Ответы [ 3 ]

4 голосов
/ 24 мая 2011

Предполагая, что dat содержит ваши данные, мы обрабатываем, используя strsplit() до

tt <- matrix(unlist(strsplit(dat$V3, split = "")), ncol = 13, byrow = TRUE)

дает:

> tt
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
[1,] "a"  "a"  "a"  "a"  "a"  "a"  "b"  "b"  "b"  "a"   "b"   "a"   "b"  
[2,] "a"  "b"  "a"  "b"  "a"  "a"  "a"  "b"  "a"  "a"   "a"   "b"   "b"  
[3,] "b"  "a"  "b"  "b"  "b"  "a"  "b"  "a"  "a"  "b"   "b"   "b"   "a"

Мы можем получить желаемые результаты, стараясь правильно установить уровни:

apply(tt, 2, function(x) c(table(factor(x, levels = c("a","b")))))

, что дает:

> apply(tt, 2, function(x) c(table(factor(x, levels = c("a","b")))))
  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
a    2    2    2    1    2    3    1    1    2     2     1     1     1
b    1    1    1    2    1    0    2    2    1     1     2     2     2

Чтобы автоматизировать выбор подходящих уровней, мы могли бы сделать что-то вроде:

> lev <- levels(factor(tt))
> apply(tt, 2, function(x, levels) c(table(factor(x, levels = lev))), 
+       levels = lev)
  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
a    2    2    2    1    2    3    1    1    2     2     1     1     1
b    1    1    1    2    1    0    2    2    1     1     2     2     2

, где в первой строке мы рассматриваем tt как вектор и извлекаем уровни после временного преобразования tt в фактор. Затем мы передаем эти уровни (lev) на шаг apply(), вместо того, чтобы явно указывать уровни.

2 голосов
/ 24 мая 2011

РЕДАКТИРОВАТЬ: решение исправлено после комментариев Гэвин Симпсон.Теперь это работает


Чтобы избежать многих преобразований в фактор, вы можете использовать следующий трюк с индексами и tapply:

tt <- c("aaaaaabbbabab","ababaaabaaabb","babbbabaabbba")

ttstr <- strsplit(tt,"")
ttf <- factor(unlist(ttstr))
n <- length(ttstr[[1]])
k <- length(ttstr)

> do.call(cbind,tapply(ttf,rep(1:n,k),table))
  1 2 3 4 5 6 7 8 9 10 11 12 13
a 2 2 2 1 2 3 1 1 2  2  1  1  1
b 1 1 1 2 1 0 2 2 1  1  2  2  2

, который дает ускорение метода примерно в 7 разпоказано @ Gavin

> benchmark(method1(tt),method2(tt),replications=1)
         test replications elapsed relative user.self 
1 method1(tt)            1    0.89 1.000000      0.89   
2 method2(tt)            1    6.99 7.853933      6.98     
0 голосов
/ 24 мая 2011

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

foo <- data.frame(
    V1 = c("X","C","V"),
    V2 = c("N","T","H"),
    V3 = c("aaaaaabbbabab","ababaaabaaabb","babbbabaabbba"))

n <- nchar(as.character(foo$V3)[1])
tabA <- table(unlist(gregexpr("a",foo$V3)),exclude=-1)
tabB <- table(unlist(gregexpr("b",foo$V3)),exclude=-1)

res <- matrix(0,2,n)

res[1,as.numeric(names(tabA))] <- tabA
res[2,as.numeric(names(tabB))] <- tabB

rownames(res) <- c("a","b")
res
  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
a    2    2    2    1    2    3    1    1    2     2     1     1     1
b    1    1    1    2    1    0    2    2    1     1     2     2     2

Без ячейки с нулевым счетом вы могли бы просто сделать rbind(tabA,tabB).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...