/ / R - Łączenie wierszy ramki danych w wielu warunkach - r, dataframe

R - Łączenie rzędów ramek danych w wielu warunkach - r, ramka danych

EDYTOWAĆ Mam ramkę danych jak poniżej: zwróć uwagę na to COL1 ma zduplikowane wpisy, mogą je mieć COL2 i COL3w dowolnej kolejności, tj. mogą wystąpić w dowolnym miejscu między innymi kolumnami w ramce danych ... i nie ma ograniczeń co do dokładnej liczby kolumn w ramce danych ... mogą być też dołączone dodatkowe kolumny później .....

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   ... ...

Mam też wektor jak poniżej:

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

Chcę, aby wynik był taki, jak pokazano poniżej: tj

  • COL1 powinien mieć sam unikalny wpis (10,11,9)

  • COL2 powinien zawierać scalone wpisy pod nim bez duplikatów (hai pal), unikalne wiersze z różnymi wartościami COL1 nie powinnybrać pod uwagę przy scalaniu. Należy scalać tylko zduplikowane wiersze wartości COL1 ... a COL2 może wystąpić w dowolnym miejscu ramki danych (nie zawsze będzie to druga kolumna)

  • COL3 powinien zawierać sumę wpisów (2 + 3 + 1 = 6). Suma powinna być obliczona tylko dla zduplikowanych wierszy. Zduplikowane wiersze są identyfikowane na podstawie wartości COL1 ... i COL3 może również wystąpić w dowolnym miejscu ramki danych (nie zawsze będzie to trzecia kolumna).

I dla COL5, COL6, COL7(Mogę mieć dołączonych wiele kolumn później ...nie jest konieczne, że mam tylko 3 kolumny dla tego warunku) potrzebuję uogólnionego fragmentu kodu takiego, że jeśli dane wejściowe są podane jako „pierwsze” z wektora o nazwie „liczba”, wartości pierwszej obserwacji ze zduplikowanych wierszy wszystkich pozostałych kolumn należy wziąć, tj. wartości pierwszego wiersza. A jeśli dane wejściowe są podane jako „ostatnie” z wektora o nazwie „liczba”, należy wziąć wartości ostatniej obserwacji ze zduplikowanych wierszy ze wszystkich pozostałych kolumn, tj. Wartości ostatniego wiersza.

Uwaga: Dane wyjściowe powinny być przechowywane w innej ramce danych

WYJŚCIE (jeśli wejście podano jako „pierwsze”):

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

W powyższym wyniku: COL5, COL6, COL7 zawierają wartości pierwszego rzędu zduplikowanych wpisów

WYJŚCIE (jeśli wejście podano jako „ostatnie”):

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

W powyższym wyniku: COL5, COL6, COL7 zawierają wartości ostatniego wiersza zduplikowanych wpisów

Odpowiedzi:

2 dla odpowiedzi № 1

Możemy użyć 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

Jeśli używamy rozwojowej wersji data.table tj. wersja 1.9.7, to można to uprościć jako

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

Jeśli potrzebujemy ostatnich rzędów, użyj .SD[.N] zamiast .SD[1L] to znaczy

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

Instrukcje instalacji rozwojowej wersji pliku data.table to tutaj


2 dla odpowiedzi nr 2

Możesz użyć dplyr.

Jest to po prostu rozszerzenie mojego komentarz na Twoje poprzednie pytanie.

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

EDYTOWAĆ

Możesz wykonać podobną operację za pomocą last zamiast first w dplyr

Jeśli są tylko dwie opcje (pierwsza, ostatnia), możesz sprawdzić warunek za pomocą if komunikat

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 dla odpowiedzi nr 3

Spróbuj tego z podstawą 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

Zgodnie z nowym wymaganiem wypróbuj to:

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