我有一个序列s
,其中我期望每个过程值与前一个相同或1。
s = c(1,1,1,1,2,2,2,-2,3,3,4,8,8,8,9,5,5,12,6)
我想要什么:
1,1,1,1,2,2,2,3,3,4,5,5,6
我用以下代码解决了这个问题:
counter = 2
repeat{
if(s[counter] == s[counter-1] | s[counter] == s[counter-1]+1){
counter = counter+1
} else{
s = s[-counter]
}
if(counter >= length(s)) break
}
然而,这看起来相当“肮脏”和低效。有没有计算上耗时更少的解决方案?
编辑
R概念翻译成Rcpp:
Rcpp::cppFunction('LogicalVector foo(NumericVector s) {
int n = s.size();
Rcpp::LogicalVector keep(n);
keep[0] = 1;
int last = 0;
for (int i = 1; i < n; i++) {
if (s[i] - s[last] == 0) {
keep[i] = 1;
} else if (s[i] - s[last] == 1) {
keep[i] = 1;
last = i;
}
}
return keep;
}')
s[foo(s)]
# [1] 1 1 1 1 2 2 2 3 3 4 5 5 6
原始解决方案(非常相似,但不如Flick先生的):
另一个稍微高效的R循环。然而,如果效率很重要,Rcpp可能是一个不错的选择。
keep = vector(length = length(s))
keep[1] = TRUE
last_keep = 1L
for (counter in 2:length(s)) {
if ((s[counter] - s[last_keep]) %in% c(0, 1)) {
last_keep = counter
keep[counter] = TRUE
}
}
s[keep]
# [1] 1 1 1 1 2 2 2 3 3 4 5 5 6
这可以通过< code>Reduce来完成:
Reduce(function(prev, this)
c(prev, if (any(this %in% (prev[length(prev)] + 0:1))) this),
s)
# [1] 1 1 1 1 2 2 2 3 3 4 5 5 6
这不能被矢量化,因为一个位置上的计算依赖于先前计算的结果,但是这是紧凑的和(imo)可读的。
仅供参考,如果性能是你的主要指标,那么sindri_baldur的Rcpp和Flick先生目前的答案似乎以压倒性优势胜出:
bench::mark(
sindri_baldur = {
keep = vector(length = length(s))
keep[1] = TRUE
last_keep = 1L
for (counter in 2:length(s)) {
if ((s[counter] - s[last_keep]) %in% c(0, 1)) {
last_keep = counter
keep[counter] = TRUE
}
}
s[keep]
},
sindri_baldur_rcpp = s[foo(s)],
r2evans = {
Reduce(function(prev, this)
c(prev, if (any(this %in% (prev[length(prev)] + 0:1))) this),
s)
},
MrFlick = increasing_seq(s))
# # A tibble: 4 x 13
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result memory time gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list> <list> <list> <list>
# 1 sindri_baldur 2.62ms 3.05ms 317. 37.81KB 15.5 143 7 450.5ms <dbl [13]> <Rprofmem~ <bench_~ <tibble ~
# 2 sindri_baldur_rcpp 1us 1.4us 533120. 2.49KB 0 10000 0 18.8ms <dbl [13]> <Rprofmem~ <bench_~ <tibble ~
# 3 r2evans 28.5us 36.9us 23454. 24.67KB 18.8 9992 8 426ms <dbl [13]> <Rprofmem~ <bench_~ <tibble ~
# 4 MrFlick 2.1us 2.5us 345770. 0B 0 10000 0 28.9ms <dbl [13]> <Rprofmem~ <bench_~ <tibble ~
我看不到一个简单的基于向量的解决方案,但是一个带预分配的普通for循环在这里会有所帮助
s = c(1,1,1,1,2,2,2,-2,3,3,4,8,8,8,9,5,5,12,6)
increasing_seq <- function(x) {
keep <- logical(length(x))
current <- x[1]
for (i in seq_along(x)) {
if (x[i] == current) {
keep[i] <- TRUE
} else if (x[i] == current + 1) {
current <- current + 1
keep[i] <- TRUE
}
}
x[keep]
}
increasing_seq(s)
# [1] 1 1 1 1 2 2 2 3 3 4 5 5 6
这里我们避免重新创建不同大小的< code>s向量。通常是重新分配很慢,而不是循环。
我有一个dataframe和要删除dataframe中的列列表。让我们使用数据集作为示例。我希望删除和,只使用剩余的列。如何使用或从包中执行此操作? drop.cols中的错误:参数类型无效 我觉得我错过了一些明显的东西,因为这些看起来像是一个相当有用的操作,应该已经存在了。在Github上,有人发布了一个类似的问题,Hadley说要使用“负面索引”。那是(我想)我试过的,但没有效果。有什么建议吗
我有一个包含和以及的字符串。 我们如何删除和,同时保持机智?
问题内容: 我有一张桌子。为了快速升级/部署网站,我做了一个新表,其中包含一些新数据,方法是: 现在每个表都有一个PK列,看起来像: 重要的一点是,两个表都依赖于完全相同的序列。没有。就我的目的而言,这似乎还可以。 此后,我加载了新数据并重命名了表,以便将其作为实盘接管,而原始表变成了。现在我尝试删除: 足够公平,列默认值仍取决于顺序。 这是踢脚线。 因此,不再对序列具有任何可见的依赖关系,但是它
本文向大家介绍如何通过R中data.table中的列名删除列?,包括了如何通过R中data.table中的列名删除列?的使用技巧和注意事项,需要的朋友参考一下 我们可以通过将列设置为NULL来实现 示例 删除一列x 删除两列
问题内容: 我有脏数据。有时它包含像字符这样。我使用这些数据进行查询 对于这个角色我得到 org.hibernate.exception.GenericJDBCException:操作’IN’的排序规则(utf8_bin,IMPLICIT),(utf8mb4_general_ci,COERCIBLE),(utf8mb4_general_ci,COERCIBLE)的非法混合 如何过滤出这样的字符?我
为此,我尝试使用lapply和一个自定义函数: 我知道我可以用一堆联合声明来做到这一点,或者也许有一种方法可以用循环和联合来做到这一点。但是考虑到需要遍历的列数,我想尝试用一种更优雅的方式来完成它。