如果不仅仅是组中的值,则删除具有值的行

时间:2017-03-15 16:03:16

标签: r

R有点新,我发现自己需要根据多个条件删除行。数据框有3列,我需要删除bid = 99的行,并且rid和qid的值小于99。 rid和qid级别的所需输出为bid,其多个值小于99或bid = 99。

  rid  qid  bid
   1    1   5
   1    1   6
   1    1   99
   1    2   6
   2    1   7
   2    1   99
   2    2   2
   2    2   3
   3    1   7
   3    1   8
   3    2   1
   3    2   99
   4    1   2
   4    1   6
   4    2   1
   4    2   2
   4    2   99
   5    1   99
   5    2   99

预期产出......

  rid  qid bid
   1    1   5
   1    1   6
   1    2   6
   2    1   7
   2    2   2
   2    2   3
   3    1   7
   3    1   8
   3    2   1
   4    1   2
   4    1   6
   4    2   1
   4    2   2
   5    1   99
   5    2   99

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

您可以使用基本R函数ave生成这样的删除变量:

df$dropper <- with(df, ave(bid, rid, qid, FUN= function(i) i == 99 & length(i) > 1))

ave计算出价的功能,按rid和qid进行分组。该函数测试分组出价值i的每个元素是否为99以及i的长度是否大于1.此外,with用于减少输入。

返回

df
   rid qid bid dropper
1    1   1   5       0
2    1   1   6       0
3    1   1  99       1
4    1   2   6       0
5    2   1   7       0
6    2   1  99       1
7    2   2   2       0
8    2   2   3       0
9    3   1   7       0
10   3   1   8       0
11   3   2   1       0
12   3   2  99       1
13   4   1   2       0
14   4   1   6       0
15   4   2   1       0
16   4   2   2       0
17   4   2  99       1
18   5   1  99       0
19   5   2  99       0

然后使用df[dropper == 0, 1:3]删除不需要的观察结果,这将同时删除新变量。

答案 1 :(得分:0)

如果您只想删除bid = 99的行,请使用dplyr

library(dplyr)

 df <- df %>%
        filter(bid != 99) 

df是您的数据框。 !=表示not equal to

使用dplyr

更新了解决方案
df %>%
 group_by(rid, qid) %>%
 mutate(tempcount = n())%>%
 ungroup() %>%
 mutate(DropValue =ifelse(bid == 99 & tempcount > 1, 1,0) ) %>%
 filter(DropValue == 0) %>%
select(rid,qid,bid)

答案 2 :(得分:0)

这是一个使用dplyr的解决方案,这是一个非常富有表现力的框架来解决这类问题。

df <- read.table(text =
"  rid  qid  bid
   1    1   5
   1    1   6
   1    1   99
   1    2   6
   2    1   7
   2    1   99
   2    2   2
   2    2   3
   3    1   7
   3    1   8
   3    2   1
   3    2   99
   4    1   2
   4    1   6
   4    2   1
   4    2   2
   4    2   99
   5    1   99
   5    2   99",
header = TRUE, stringsAsFactors = FALSE)

Dplyr动词允许以接近问题条款的方式表达程序:

library(dplyr)
res <-
  df %>% 
  group_by(rid, qid) %>% 
  filter(!(any(bid < 99) & bid == 99)) %>% 
  ungroup()
# # A tibble: 15 × 3
#      rid   qid   bid
#    <int> <int> <int>
# 1      1     1     5
# 2      1     1     6
# 3      1     2     6
# 4      2     1     7
# 5      2     2     2
# 6      2     2     3
# 7      3     1     7
# 8      3     1     8
# 9      3     2     1
# 10     4     1     2
# 11     4     1     6
# 12     4     2     1
# 13     4     2     2
# 14     5     1    99
# 15     5     2    99

让我们检查一下我们得到了所需的输出:

desired_output <- read.table(text =
"  rid  qid bid
   1    1   5
   1    1   6
   1    2   6
   2    1   7
   2    2   2
   2    2   3
   3    1   7
   3    1   8
   3    2   1
   4    1   2
   4    1   6
   4    2   1
   4    2   2
   5    1   99
   5    2   99",
header = TRUE, stringsAsFactors = FALSE)
identical(as.data.frame(res), desired_output)
# [1] TRUE

答案 3 :(得分:0)

以下是allifdata.table条件的另一个选项,可以在分组之后对行进行子集化排除&#39; rid&#39;和&#39; qid&#39;

library(data.table)
setDT(df1)[, if(all(bid==99)) .SD else .SD[bid!= 99], .(rid, qid)]
#     rid qid bid
# 1:   1   1   5
# 2:   1   1   6
# 3:   1   2   6
# 4:   2   1   7
# 5:   2   2   2
# 6:   2   2   3
# 7:   3   1   7
# 8:   3   1   8
# 9:   3   2   1
#10:   4   1   2
#11:   4   1   6
#12:   4   2   1
#13:   4   2   2
#14:   5   1  99
#15:   5   2  99

或者不使用if

setDT(df1)[df1[, .I[all(bid==99) |  bid != 99], .(rid, qid)]$V1]