有趣的用例。我们可以设计一个函数,帮助您以您希望的通用方式执行此操作。
注意:
我使用了低于 b/c 的数据框,我认为最初没有(或者我只是错过了)矩阵提及,现在各种问题编辑会混淆列名和行名。 所以你应该从下面关注的位是:
# get the terms of the formula
trms <- terms(remove_spec)
# get each element (will be each group separated by `+`
elements <- attr(trms, "term.labels")
# adding in assertions to validate `col` is in `xdf` and that only
# the restricted syntax is used in the formula and that it's valid
# is up to the OP
# now, find the positions of all those strings
unlist(lapply(elements, function(y) {
if (grepl(":", y)) {
rng <- strsplit(y, ":")[[1]]
which(x[,col] == rng[1]) : which(x[,col] == rng[2])
} else {
which(x[,col] == y)
}
}), use.names = FALSE) -> to_exclude
因为我现在已经完成了这个 q(并且行名是如此 1980 年代:-)。请注意答案末尾的警告。
其他人可以随意在 OP 用例的实际矩阵答案中使用它。
我们将制作一些模拟数据(如果您想要更大的示例,我可以将示例放大):
library(dplyr) # mostly for saner data frame constructor & printing
set.seed(2018-11-18)
data_frame(
cat = LETTERS,
val1 = sample(100, length(cat), replace = TRUE),
val2 = sample(100, length(cat), replace = TRUE),
val3 = sample(100, length(cat), replace = TRUE)
) -> xdf
xdf
## # A tibble: 26 x 4
## cat val1 val2 val3
## <chr> <int> <int> <int>
## 1 A 87 98 5
## 2 B 30 69 39
## 3 C 87 1 32
## 4 D 65 46 87
## 5 E 4 69 6
## 6 F 53 20 31
## 7 G 43 51 84
## 8 H 27 43 65
## 9 I 27 9 10
## 10 J 10 94 11
## # ... with 16 more rows
(tibble 打印是 def >> 基本打印 IMO,但我离题了)。
现在,您想使用字符串来指定单个元素和范围,并确定在幕后做什么。我们需要一个函数来实现和,我们可以利用一个特殊的 R 类——forumla——来帮助实现更紧凑的语法。也就是说,能够调用这样的函数不是很好吗:
remove_rows(xdf, cat, ~B:C+F+G:I)
这将在xdf的cat列中寻找“B”的范围:“C”,找到“F”的位置,然后找到“G”的范围":"I" 并返回一个排除了那些的数据框?是的,是的。所以,让我们构建它吧!
#' @param x data frame
#' @param col bare column name to use for the comparison
#' @param formula restricted operators are `:` for range and `+` for additing selectors
remove_rows <- function(x, col, remove_spec) {
# this is pure convenience we could just as easily have forced folks
# to pass in a string (and we can modify it to handle both)
col <- as.character(substitute(col))
# get the terms of the formula
trms <- terms(remove_spec)
# get each element (will be each group separated by `+`
elements <- attr(trms, "term.labels")
# adding in assertions to validate `col` is in `xdf` and that only
# the restricted syntax is used in the formula and that it's valid
# is up to the OP
# now, find the positions of all those strings
unlist(lapply(elements, function(y) {
if (grepl(":", y)) {
rng <- strsplit(y, ":")[[1]]
which(x[,col] == rng[1]) : which(x[,col] == rng[2])
} else {
which(x[,col] == y)
}
}), use.names = FALSE) -> to_exclude
# and get rid of those puppies
x[-to_exclude,]
}
现在我们可以实事求是了:
remove_rows(xdf, cat, ~B:C+F+G:I)
## # A tibble: 20 x 4
## cat val1 val2 val3
## <chr> <int> <int> <int>
## 1 A 87 98 5
## 2 D 65 46 87
## 3 E 4 69 6
## 4 J 10 94 11
## 5 K 37 86 52
## 6 L 89 64 44
## 7 M 61 10 28
## 8 N 79 52 89
## 9 O 71 33 77
## 10 P 45 33 77
## 11 Q 56 97 29
## 12 R 10 28 39
## 13 S 25 7 71
## 14 T 86 57 51
## 15 U 92 2 15
## 16 V 25 36 12
## 17 W 90 78 10
## 18 X 20 82 90
## 19 Y 39 84 13
## 20 Z 43 93 18
函数的命名很糟糕,因此您可能想要更改它,并且您确实应该添加一些参数检查和验证,但我相信这可以满足您的需求(假设您真的确定数据帧的顺序是您认为的顺序)。
此外,这是不完美的,因为字符串被限制为公式(其中一个限制是它们不能以没有反引号的数字开头)。但是,您没有提供真实字符串的样本。