применить сумму к data.frame, сгруппированному по подстроке, с R - PullRequest
3 голосов
/ 24 февраля 2012

Пример данных:

> mat1 = as.data.frame(matrix(c("D-J10-N1","D-J10-N2","D-J2-N1","D-J2-N2",3,6,5,7,8,4,2,3,4,1,2,3), ncol = 4));
> mat1
        V1 V2 V3 V4
1 D-J10-N1  3  8  4
2 D-J10-N2  6  4  1
3  D-J2-N1  5  2  2
4  D-J2-N2  7  3  3

желаемый вывод:

> results
        V1 V2 V3 V4
    1 J10  9  12  5
    2 J2   12 5   5

Итак, мне нужно сложить V2 в V4 подстрокой V1, а затем вернуть эту подстроку в моих результатах. Я могу определить свои группы как:

> groups <- substr(mat1[,1],1,5)
> groups
[1] "D-J10" "D-J10" "D-J2-" "D-J2-"

Я подумал об использовании строки как:

> rowsum(mat1,groups, reorder = TRUE)

Но, как представляется, rowSum принимает только числовые значения для групп? Я посмотрел в приложении семейные функции, но не нашел удачи .... Есть идеи, как это решить?

Большое спасибо за помощь !!

Ответы [ 3 ]

2 голосов
/ 24 февраля 2012

Это помогает настроить data.frame так, чтобы классы столбцов подходили немного лучше (в настоящее время они все факторы).

mat1 <- data.frame(V1=c("D-J10-N1","D-J10-N2","D-J2-N1","D-J2-N2"),V2=c(3,6,5,7),V3=c(8,4,2,3),V4=c(4,1,2,3))

Тогда вы можете использовать aggregate и sub длявыберите свою подстроку:

aggregate(mat1[-1],by=list(sub("D-(J[0-9]+)-[A-Z0-9]+","\\1",mat1$V1)),sum)
  Group.1 V2 V3 V4
1     J10  9 12  5
2      J2 12  5  5
1 голос
/ 24 февраля 2012

Во-первых, давайте немного изменим ваши данные.

mat1 <- data.frame(V1 = c("D-J10-N1","D-J10-N2","D-J2-N1","D-J2-N2"),
                   V2 = c(3,6,5,7),
                   V3 = c(8,4,2,3),
                   V4 = c(4,1,2,3))

Если вы посмотрите на str ваших исходных данных, все они будут символами. Именно поэтому rowums erros.

Использование strsplit и lapply позволяет начать работу:

mat1$new.V1 <- unlist(lapply(strsplit(mat1$V1, '-'), '[', 2))

Однако, в зависимости от данных в первом столбце, вы можете использовать gsub и регулярное выражение:

gsub('.+-([0-z]+)-.+','\\1',mat1$V1)

или что-то в этом роде ...

Тогда я бы посмотрел на пакет plyr.

ddply(mat1, .(new.V1), summarise, sums = sum(V2, V3, V4))

Или как уродливый путник:

ddply(mat1, .(unlist(lapply(strsplit(mat1$V1, '-'), '[', 2))), summarise, sum(V2, V3, V4))
0 голосов
/ 15 января 2014

Пакет data.table подходит для такого типа агрегации. Как уже говорили другие, я бы переформатировал ваши данные, например:

library(data.table)
mat1 <- data.table(V1=c("D-J10-N1","D-J10-N2","D-J2-N1","D-J2-N2"),
                   V2=c(3,6,5,7),
                   V3=c(8,4,2,3),
                   V4=c(4,1,2,3),
                   key="V1")

Тогда вы можете суммировать это так:

mat1[, lapply(.SD, sum), by=list(V1b=gsub(".*\\-(.*)\\-.*", "\\1", mat1[,V1]))]
#   V1b V2 V3 V4
#1: J10  9 12  5
#2:  J2 12  5  5

Часть lapply(.SD, sum) суммирует каждый столбец, а часть by группирует его по запрошенной подстроке (используя gsub и регулярное выражение).

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