2011-03-05 12 views
5

Este es un problema realmente simple, pero no puedo encontrar la manera de guiarlo. No puedo avanzar hasta que lo resuelva. Soy realmente nuevo en R y en el uso del código, y estoy repasando varios manuales introductorios, pero aún no he encontrado nada para este problema específico.Crear un nuevo marco de datos en R a partir de un marco de datos existente e inadecuado

En general, este es el problema. Digamos que tengo una trama de datos llamada x que se parece a:

a <- c(1995,1995,1995,1996,1997,1997,1997,1998) 
b <- c(1,2,3,1,2,3,4,1) 
c <- c(5,7,8,2,4,5,7,8) 
(x <- data.frame(a,b,c)) 
    a b c 
1 1995 1 5 
2 1995 2 7 
3 1995 3 9 
4 1996 1 2 
5 1997 2 4 
6 1997 3 5 
7 1997 4 7 
8 1998 1 8 

Hay varias entradas para algunos de los años en la columna a (es decir, 1995 aparece 3 veces), cuando en realidad sólo quiero una entrada para cada año . Si trato de trazar la columna a en la columna c, terminaré con varios puntos para cada fecha, pero eso no es útil. No me importa la columna b, pero Quiero sumar entradas para la columna c para cada año, de modo que termine con un marco de datos con una entrada para cada año. Teniendo en cuenta los datos anteriores, un marco de datos resultante se vería así:

 a c 
1 1995 21 
2 1996 2 
3 1997 16 
4 1998 8 

¿Alguna idea?

+0

Consejo: evitar llamar a las cosas 'C'. Recuerde que 'c' es una función para crear vectores. – csgillespie

+0

@csgillespie: Eso es cierto para los objetos. No es un problema tan grande para los nombres de columna. –

+1

@Joshua: Cierto, pero (algunas personas) pueden tener la tentación de hacer 'c = df $ c' sin pensar. – csgillespie

Respuesta

10

La biblioteca plyr es útil para tareas de agregación tales como éstos. plyr también juega muy bien con ggplot2 gráficos. En mi opinión, el beneficio de plyr es que defines explícitamente la estructura de la entrada y la salida. Aquí estamos pasando en un objeto data.frame y también queremos un data.frame después del procesamiento, entonces usaremos ddply. La primera letra corresponde al objeto de entrada y la segunda a la salida. Así que si queríamos ir desde un objeto a listdata.frame, que usaríamos ldply, etc.

library(ggplot2) #Loads plyr 

text <- "a b c 
1995 1 5 
1995 2 7 
1995 3 9 
1996 1 2 
1997 2 4 
1997 3 5 
1997 4 7 
1998 1 8 
" 

df <- read.table(textConnection(text), header = TRUE) 

#Create plotData data.frame that groups by the "a" column and returns the sum of "c" 
plotData <- ddply(df, "a", summarise, totalc = sum(c)) 

#plotting with ggplot 
qplot(factor(a), totalc, data = plotData) 
+2

Si fuera un apostador, habría puesto dinero en la respuesta 'plyr' siendo aceptado como el mejor. –

9
aggregate(x[,"c",drop=FALSE], by=x[,"a",drop=FALSE], sum) 

El drop=FALSE es asegurar el objeto creado por subconjuntos x es un data.frame. Si omite drop=FALSE, las dimensiones del data.frame se eliminarán (porque solo está accediendo a una columna del data.frame) y el resultado del subconjunto será un vector. Vea ?"[" y ?drop para más detalles.

ACTUALIZACIÓN: Estoy de acuerdo con Gavin que la interfaz es más limpio fórmula:

aggregate(c ~ a, data=x, sum) 
+4

¿no sería simplemente más fácil usar la interfaz de fórmula en este caso? 'aggregate (c ~ a, data = x, sum)' Además, solo necesita el 'drop' en la versión' by' ya que este argumento solo toma una lista, por ejemplo, esto también funciona bien: 'aggregate (x [ , "c2"], por = lista (Año = x [, "c1"]), suma) ' –

+4

@Gavin: muy buen punto acerca de la interfaz de la fórmula. La razón por la que utilicé 'drop' en el primer argumento es para que el nombre de la columna persista en el nuevo objeto. –

+1

buena réplica - touché - no había notado que el nombre se conservaba si el primer argumento es un marco de datos. +1. –

9

Usted necesita tapply. Por ejemplo,

## Your data 
c1 = c(1995, 1995, 1995, 1996, 1997, 1997, 1997, 1998) 
c2 = c(5, 7, 9, 2, 4, 5, 7, 8) 
x = data.frame(c1, c2) 


y = tapply(x$c2, x$c1, sum) 
names(y) ## For the years 
as.vector(y) 

## So to get a data frame 
data.frame(a=names(y), c=as.vector(y)) 
+0

Buena respuesta, pero necesita otro paso para convertir 'y' en un data.frame con columnas" a "y" c ". –

+0

@Joshua: He agregado ese paso a la respuesta en caso de que no estuviera claro. Realmente no puedo decidir qué respuesta prefiero, la tuya o la mía. – csgillespie

Cuestiones relacionadas