2013-06-29 3 views
4

У меня есть кадр df данных со строками, которые являются дубликатами для столбца имен, но не для столбца значений:среднее между дублированных строк в R

name value etc1 etc2 
A  9  1  X 
A  10  1  X 
A  11  1  X 
B  2  1  Y 
C  40  1  Y 
C  50  1  Y 

мне нужно объединить повторяющиеся имена в одну строку, в то время как вычисляя среднее значение над столбцом значений. Ожидаемый результат заключается в следующем:

name value etc1 etc2 
A  10  1  X 
B  2  1  Y 
C  45  1  Y 

Я пытался использовать df[duplicated(df$name),], но, конечно, это не дает мне среднее за дубликатами. Я хотел бы использовать aggregate(), но проблема в том, что часть FUN этой функции будет применяться ко всем другим столбцам, а также, среди прочих проблем, она не сможет вычислить контент char. Поскольку все остальные столбцы имеют одинаковый контент по «дубликатам», мне нужно, чтобы они были агрегированы, как и столбцы имен. Любые намеки ...?

+1

ли ваши другие столбцы 'etcX' также гарантированно быть одинаковым для строк с тем же' name'? –

+0

@HongOoi Да, я так считаю, я отфильтровал их на предыдущем шаге, чтобы получить аналогичное содержимое. – biohazard

+0

@agstudy Извините, ожидаемый результат уже был включен в мой пост, но я забыл сказать это в моем предложении. Это было исправлено пользовательскими метриками. – biohazard

ответ

8

Здесь data.table решение. Решение является общим в том смысле, что оно будет работать даже для data.frame с 60 столбцами. Поскольку I группы данные по всем переменным различных значения (Посмотрите, как создать ключи ниже)

library(data.table) 
dat <- read.table(text='name value etc1 etc2 
A  9  1  X 
A  10  1  X 
A  11  1  X 
B  2  1  Y 
C  40  1  Y 
C  50  1  Y',header=TRUE) 
keys <- colnames(dat)[!grepl('value',colnames(dat))] 
X <- as.data.table(dat) 
X[,list(mm= mean(value)),keys] 
    name etc1 etc2 mm 
1: A 1 X 10 
2: B 1 Y 2 
3: C 1 Y 45 

EDIT распространяется на более чем одного значения переменной

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

name value etc1 etc2  value1 
1 A  9 1 X 2.1763485 
2 A 10 1 X -0.7954326 
3 A 11 1 X -0.5839844 
4 B  2 1 Y -0.5188709 
5 C 40 1 Y -0.8300233 
6 C 50 1 Y -0.7787496 

выше решение может быть продлен, как это:

X[,lapply(.SD,mean),keys] 
    name etc1 etc2 value  value1 
1: A 1 X 10 0.2656438 
2: B 1 Y  2 -0.5188709 
3: C 1 Y 45 -0.8043865 

Это вычислит среднее значение для всех переменных, которых нет в списке ключей.

1

Предполагая, что ваш dataframe является df.

install.packages("plyr") 
library(plyr) 



df<- structure(list(name = structure(c(1L, 1L, 1L, 2L, 3L, 3L), .Label = c("A", 
    "B", "C"), class = "factor"), value = c(9L, 10L, 11L, 2L, 40L, 
    50L), etc1 = c(1L, 1L, 1L, 1L, 1L, 1L), etc2 = structure(c(1L, 
    1L, 1L, 2L, 2L, 2L), .Label = c("X", "Y"), class = "factor")), .Names = c("name", 
    "value", "etc1", "etc2"), class = "data.frame", row.names = c(NA, 
    -6L)) 

df.m<-ddply(df,.(name),summarize, value=mean(value),etc1=head(etc1,1),etc2=head(etc2,1)) 

df.m 
name value etc1 etc2 
1 A  10 1 X 
2 B  2 1 Y 
3 C  45 1 Y 
+0

Спасибо большое! Однако есть одно предостережение. В реальном наборе данных у меня есть около 60 других столбцов, которые не изменяются по дубликатам и должны быть оставлены нетронутыми, нужно ли вводить их один за другим в качестве аргументов 'ddply()' или есть ли технология быстрого доступа? – biohazard

+0

Сделаем это, большое спасибо: D – biohazard

2

Код (написанный метриками) почти работает, за исключением одного места (.name). Я слегка изменил его:

sample<- structure(list(name = structure(c(1L, 1L, 1L, 2L, 3L, 3L), .Label = c("A", 
    "B", "C"), class = "factor"), value = c(9L, 10L, 11L, 2L, 40L, 
    50L), etc1 = c(1L, 1L, 1L, 1L, 1L, 1L), etc2 = structure(c(1L, 
    1L, 1L, 2L, 2L, 2L), .Label = c("X", "Y"), class = "factor")), .Names = c("name", 
    "value", "etc1", "etc2"), class = "data.frame", row.names = c(NA, 
    -6L)) 

sample.m <- ddply(sample, 'name', summarize, value =mean(value), etc1=head(etc1,1), etc2=head(etc2,1)) 

sample.m 
     name value etc1 etc2 
    1 A 10 1 X 
    2 B  2 1 Y 
    3 C 45 1 Y 
+0

Большое спасибо! Не могли бы вы узнать, есть ли ярлык, который я могу использовать, так что мне не нужно вводить имена всех остальных столбцов? На самом деле их гораздо больше, чем в примере, который я дал. – biohazard

+0

@agstudy Я тоже этого не знал. Спасибо за указание на это. – biohazard

7

Вы можете использовать aggregate() функцию, как показано ниже:

aggregate(df$value,by=list(name=df$name,etc1=df$etc1,etc2=df$etc2),data=df,FUN=mean) 
+1

Вам не нужно использовать 'df $' внутри агрегата, потому что у него есть аргумент данных, в котором вы указываете источник данных (в этом случае df).Существует также интерфейс формул для совокупности, который может быть легче читать. –

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