根据R中多个列的条件,仅选取特定列

时间:2016-08-30 17:13:33

标签: r select unique

我有一个数据框,比如说

df <- data.frame(x = c(1,2,5,6,3,3,3,6,8,8,8,8),
             y = c(1,1,1,1,1,2,3,1,1,2,3,4),
             z = c("a","b","c","d","e","f","g","h","i","j","k","l"))

看起来像这样

   x y z
1  1 1 a
2  2 1 b
3  5 1 c
4  6 1 d
5  3 1 e
6  3 2 f
7  3 3 g
8  6 1 h
9  8 1 i
10 8 2 j
11 8 3 k
12 8 4 l

我想从列x中选择唯一的元素,基于列y使得y应该是最大的(在这种情况下,对于行号5到7是3'3,我想选择x = 3对应于y = 3(最大值),类似于x = 8,我想选择y = 4行)

输出应该如下所示

  x y z
1 1 1 a
2 2 1 b
3 5 1 c
4 6 1 d
5 3 3 g
6 6 1 h
7 8 4 l

我有一个解决方案,我在解决方案中发布,但如果有更好的方法来实现这一点,我的解决方案只适用于这种特定情况(选择最大的)什么是一般案例解决方案此?

5 个答案:

答案 0 :(得分:2)

使用dplyr

的一种解决方案
library(dplyr) 
df %>% 
 group_by(x) %>% 
 slice(max(y))

#      x     y     z
#  (dbl) (dbl) (chr)
#1     1     1     a
#2     2     1     b
#3     3     3     g
#4     5     1     c
#5     6     1     d
#6     8     4     l

base R替代方案正在使用aggregate

aggregate(y~x, df, max)

答案 1 :(得分:2)

您可以使用dplyr链和dplyr的{​​{1}}函数获得相同的结果。使用group_by函数后,链中的其余函数将应用于组中,而不是整个data.frame。所以,group_by每个filter的分组值max(y)只留下x。这可以扩展为用于min y或特定值。

我认为使用ungroupgroup_by链末尾的数据通常是一种很好的做法,以避免任何意外行为。

library(dplyr)
df <- data.frame(x = c(1,2,5,6,3,3,3,6,8,8,8,8),
             y = c(1,1,1,1,1,2,3,1,1,2,3,4),
             z = c("a","b","c","d","e","f","g","h","i","j","k","l"))
df %>% 
  group_by(x) %>% 
  filter(y==max(y)) %>% 
  ungroup()

为了使其更通用...而是说您希望mean y代表x而不是max。然后,您可以使用summarise函数代替filter,如下所示。

df %>% 
  group_by(x) %>% 
  summarise(y=mean(y)) %>% 
  ungroup()

答案 2 :(得分:1)

使用data.table我们可以使用df[order(z), .I[which.max(y)], by = x]来获取感兴趣的rownumbers,例如:

library(data.table)
setDT(df)
df[df[order(z), .I[which.max(y)], by = x][, V1]]

   x y z
1: 1 1 a
2: 2 1 b
3: 5 1 c
4: 6 1 d
5: 3 3 g
6: 8 4 l

答案 3 :(得分:0)

这是我使用dplyr软件包的解决方案

library(dplyr)
df <- data.frame(x = c(1,2,5,6,3,3,3,6,8,8,8,8),
                 y = c(1,1,1,1,1,2,3,1,1,2,3,4),
                 z = c("a","b","c","d","e","f","g","h","i","j","k","l"))
df <- arrange(df,desc(y))
df_out <- df[!duplicated(df$x),]
df_out

打印df_out

  x y z
1 8 4 l
2 3 3 g
6 1 1 a
7 2 1 b
8 5 1 c
9 6 1 d

答案 4 :(得分:0)

假设数据框按照示例中的df[order(df$x, df$y),]排序,您可以使用基本R函数splitlapplydo.call/rbind来提取使用&#34; split / apply / combine&#34;方法

do.call(rbind, lapply(split(df, df$x), function(i) i[nrow(i),]))
  x y z
1 1 1 a
2 2 1 b
3 3 3 g
5 5 1 c
6 6 1 h
8 8 4 l

split将data.frame分解为基于x的列表。此列表被送到lapply,它选择每个data.frame的最后一行,并将这一行data.frames作为列表返回。然后使用rbind将此列表do.call编辑到单个数据框中。