/ / R-複数の条件でデータフレーム行を結合-r、データフレーム

R - 複数の条件でのデータフレーム行の結合 - r、dataframe

EDIT 私は以下のようなデータフレームを持っています:注意してください COL1 エントリが重複しています。COL2とCOL3はつまり、データフレーム内の他の列の間のどこにでも発生する可能性があります...データフレーム内の列の正確な数に制限はありません..

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

また、次のようなベクターもあります。

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

以下に示すように、出力を次のようにします。

  • COL1 一意のエントリのみが必要です(10,11,9)

  • COL2 重複することなく、その下にマージされたエントリを含める必要があります(hai pal)、 異なるCOL1値を持つ一意の行は、 "t"マージを検討してください。 COL1値の重複行のみをマージする必要があります... COL2はデータフレーム内のどこでも発生する可能性があります(常に2番目の列になるとは限りません)

  • COL3 エントリの合計(2 + 3 + 1 = 6)を含める必要があります。 合計は、重複行のみに対して計算する必要があります。重複行はCOL1値に基づいて識別されます... COL3はデータフレーム内のどこでも発生する可能性があります(常に3列目とは限りません)。

そして COL5, COL6, COL7(後で多くの列が追加されることがあります...この条件に3列しかない必要はありません)「number」という名前のベクトルから「first」として入力が与えられた場合、残りのすべての列の重複行からの最初の観測値がつまり、最初の行の値を取得する必要があります。また、入力が「number」という名前のベクトルから「last」として指定されている場合、残りのすべての列の重複行からの最後の観測値、つまり最後の行の値を取得する必要があります。

注意: 出力は別のデータフレームに保存する必要があります

OUTPUT(入力が「最初」として指定されている場合):

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

上記の出力:COL5、COL6、COL7には、重複エントリの最初の行の値が含まれています

OUTPUT(入力が「最後」として与えられた場合):

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

上記の出力:COL5、COL6、COL7には、重複エントリの最後の行の値が含まれています

回答:

回答№1は2

我々は使用することができます 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

開発版を使用している場合 data.table つまり、v.1.9.7、これは次のように簡略化できます

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

最後の行が必要な場合は、 .SD[.N] の代わりに .SD[1L] すなわち、

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

data.tableの開発バージョンをインストールする手順は次のとおりです。 ここに


回答№2については2

あなたは使うことができます dplyr.

これは基本的に私の拡張です コメント あなたの前の質問に。

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

EDIT

同様の操作を使用して行うことができます last の代わりに firstdplyr

オプションが2つ(最初、最後)しかない場合は、 if ステートメント

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))
}

回答№3の場合は1

ベース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

新しい要件に従って、これを試してください:

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