/ / R: combinación de filas de marcos de datos en varias condiciones: r, marco de datos

R - Combinación de filas de marcos de datos en múltiples condiciones - r, marco de datos

EDITAR Tengo un marco de datos como el siguiente: tenga en cuenta que COL1 está teniendo entradas duplicadas, COL2 y COL3 pueden seren cualquier orden, es decir, pueden ocurrir en cualquier lugar entre otras columnas en el marco de datos ... y no hay limitación en el número exacto de columnas en el marco de datos ... puede haber columnas adicionales también agregadas más tarde .....

COL1 COL2 COL3 COL5 COL6 COL7 ... ... (goes on)
10  hai    2   15  10    6   ... ...
10  hai    3   25  20   12   ... ...
10  pal    1   35  30   18   ... ...
11  rfm    9   22  32    9   ... ...
9  rtf    8   34  54   10   ... ...

También tengo un vector como el siguiente:

number <- c("first", "last")

Quiero que la salida sea así como se muestra a continuación: es decir

  • COL1 debe tener solo la entrada única (10,11,9)

  • COL2 debe contener las entradas fusionadas debajo sin duplicados (hai pal), las filas únicas con valores COL1 distintos no deberían "tser considerado para fusionarse. Solo se deben combinar filas duplicadas de valores COL1 ... y COL2 puede aparecer en cualquier parte del marco de datos (no siempre será la segunda columna)

  • COL3 debe contener la suma de las entradas (2 + 3 + 1 = 6). La suma debe calcularse solo para filas duplicadas. Las filas duplicadas se identifican en función de los valores de COL1 ... y COL3 también puede aparecer en cualquier parte del marco de datos (no siempre será la tercera columna).

Y para COL5, COL6, COL7(Es posible que tenga muchas columnas agregadas más tarde ...no es necesario que solo tenga 3 columnas para esta condición) necesito un fragmento de código generalizado de modo que si la entrada se da como "primera" del vector llamado "número", los valores de la primera observación de las filas duplicadas de todas las columnas restantes deben tomarse, es decir, los valores de la primera fila. Y si la entrada se da como "última" del vector llamado "número", los valores de la última observación de las filas duplicadas de todas las columnas restantes deben tomarse, es decir, los valores de la última fila.

Nota: La salida debe almacenarse en otro marco de datos

SALIDA (si la entrada se da como "primera"):

COL1    COL2   COL3 COL5 COL6 COL7
10      hai pal 6   15    10    6
11      rfm     9   22    32    9
9      rtf     8   34    54   10

En el resultado anterior: COL5, COL6, COL7 contienen los valores de la primera fila de entradas duplicadas

SALIDA (si la entrada se da como "última"):

COL1    COL2   COL3 COL5 COL6 COL7
10      hai pal 6   15    10    6
11      rfm     9   22    32    9
9      rtf     8   34    54   10

En el resultado anterior: COL5, COL6, COL7 contienen los valores de la última fila de entradas duplicadas

Respuestas

2 para la respuesta № 1

Nosotros podemos usar data.table

library(data.table)
setDT(df1)[, .(COL2 = paste(unique(COL2), collapse= " "),
COL3 = sum(COL3),
COL5 = COL5[1L],
COL6 = COL6[1L],
COL7 = COL7[1L]), by = COL1]
#   COL1    COL2 COL3 COL5 COL6 COL7
#1:   10 hai pal    6   15   10    6

Si estamos usando la versión de desarrollo de data.table es decir, v.1.9.7, entonces esto se puede simplificar como

setDT(df1)[, c(COL2 = paste(unique(COL2), collapse=" "),
COL3 = sum(COL3) ,.SD[1L]), by = COL1, .SDcols=COL5:COL7]
#    COL1    COL2 COL3 COL5 COL6 COL7
#1:   10 hai pal    6   15   10    6

Si necesitamos las últimas filas, use .SD[.N] en lugar de .SD[1L] es decir

setDT(df1)[, c(COL2 = paste(unique(COL2), collapse=" "),
COL3 = sum(COL3) ,.SD[.N]), by = COL1, .SDcols=COL5:COL7]
#   COL1    COL2 COL3 COL5 COL6 COL7
#1:   10 hai pal    6   35   30   18

Las instrucciones para instalar la versión de desarrollo de data.table son aquí


2 para la respuesta № 2

Puedes usar dplyr.

Esto es básicamente solo una extensión de mi comentario en su pregunta anterior

library(dplyr)
new_df <- df %>% group_by(COL1) %>%
summarise(COL2 = paste0(unique(COL2), collapse = " "),
COL3 = sum(COL3),
COL5 = first(COL5),
COL6 = first(COL6),
COL7 = first(COL7))
new_df
#    COL1    COL2     COL3  COL5  COL6  COL7
#    <int>   <chr>   <int> <int> <int> <int>
#1    10    hai pal     6    15    10     6

EDITAR

Puedes hacer una operación similar usando last en lugar de first en dplyr

Si solo hay dos opciones (primera, última), puede verificar la condición con un if declaración

if(number == "first") {
new_df <- df %>% group_by(COL1) %>%
summarise(COL2 = paste0(unique(COL2), collapse = " "),
COL3 = sum(COL3),
COL5 = first(COL5),
COL6 = first(COL6),
COL7 = first(COL7))
} else
{
new_df <- df %>% group_by(COL1) %>%
summarise(COL2 = paste0(unique(COL2), collapse = " "),
COL3 = sum(COL3),
COL5 = last(COL5),
COL6 = last(COL6),
COL7 = last(COL7))
}

1 para la respuesta № 3

Prueba esto con la base R:

get.df <- function(df, input) {
cbind.data.frame(COL1=unique(df$COL1),
COL2=paste(unique(df$COL2), collapse=" "),
COL3=sum(df$COL3),
df[ifelse(input == "first", 1, nrow(df)),names(df)[-1:-3]])
}

get.df(df, "first")
# COL1    COL2 COL3 COL5 COL6 COL7
# 1   10 hai pal    6   15   10    6

get.df(df, "last")
# COL1    COL2 COL3 COL5 COL6 COL7
# 3   10 hai pal    6   35   30   18

Según su nuevo requisito, intente esto:

df <- read.table(text="COL1 COL2 COL3 COL5 COL6 COL7
10  hai    2   15  10    6
10  hai    3   25  20   12
10  pal    1   35  30   18
11  rfm    9   22  32    9
9  rtf    8   34  54   10", header=TRUE)

get.df <- function(df, input) {

dups <- unique(df[duplicated(df$COL1),]$COL1)
df.dup <- df[df$COL1 %in% dups,]
df.nondup <- df[!(df$COL1 %in% dups),]
rbind(cbind.data.frame(COL1=unique(df.dup$COL1),
COL2=paste(unique(df.dup$COL2), collapse=" "),
COL3=sum(df.dup$COL3),
df.dup[ifelse(input == "first", 1, nrow(df.dup)),names(df.dup)[-1:-3]]),
df.nondup)
}

number <- c("first", "last")

get.df(df, "first")

COL1    COL2 COL3 COL5 COL6 COL7
1   10 hai pal    6   15   10    6
4   11     rfm    9   22   32    9
5    9     rtf    8   34   54   10

get.df(df, "last")

COL1    COL2 COL3 COL5 COL6 COL7
3   10 hai pal    6   35   30   18
4   11     rfm    9   22   32    9
5    9     rtf    8   34   54   10