R - 在多个条件下组合数据帧行

时间:2016-10-13 07:03:13

标签: r dataframe

修改 我有一个如下数据框:请注意COL1有重复的条目,COL2& COL3可以按任何顺序排列,即它们可以出现在数据帧中其他列之间的任何位置......并且对数据帧中的确切列数没有限制。以后可能还会添加其他列..... / p>

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值的唯一行进行合并。只应合并重复的COL1值行...并且COL2可以出现在数据框的任何位置(它不会总是第二列)

  • COL3应包含条目总和(2 + 3 + 1 = 6)。应该仅为重复行计算 Sum。基于COL1值识别重复行...并且COL3也可以出现在数据框中的任何位置(它不会总是第3列)。

对于COL5COL6COL7(我可能会在后面添加许多列...不需要我只有3列用于此条件)我需要一个广义的片段例如,如果输入从名为“number”的向量中给出为“first”,则需要从所有剩余列的重复行中获取第一次观察的值,即第一行值。如果输入从名为“number”的向量中作为“last”给出,则需要从所有剩余列的重复行中进行最后一次观察的值,即最后一行值。

注意:输出应存储在另一个数据帧

OUTPUT(如果输入为“first”):

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(如果输入为“last”):

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包含重复条目的最后一行值

3 个答案:

答案 0 :(得分:2)

您可以使用dplyr

这基本上只是我之前问题的comment的扩展。

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

修改

您可以使用last代替first中的dplyr进行类似的操作

如果只有两个选项(第一个,最后一个),您可以使用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))
}

答案 1 :(得分:2)

我们可以使用Column2

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 的devel版本,即v.1.9.7,那么这可以简化为

data.table

如果我们需要最后一行,请使用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]

安装devel版本的data.table的说明是here

答案 2 :(得分: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