[英]Is there a vectorized parallel max() and min()?
I have a data.frame
with columns "a" and "b".我有一个包含“a”和“b”列的
data.frame
。 I want to add columns called "high" and "low" that contain the highest and the lowest among columns a and b.我想添加名为“高”和“低”的列,其中包含 a 和 b 列中的最高和最低。
Is there a way of doing this without looping over the lines in the dataframe?有没有办法在不遍历数据帧中的行的情况下执行此操作?
edit: this is for OHLC data, and so the high and low column should contain the highest and lowest element between a and b on the same line, and not among the whole columns.编辑:这是用于 OHLC 数据,因此高和低列应包含同一行上 a 和 b 之间的最高和最低元素,而不是整个列中。 sorry if this is badly worded.
对不起,如果这措辞不好。
Sounds like you're looking for pmax
and pmin
("parallel" max/min):听起来您正在寻找
pmax
和pmin
(“平行”最大值/最小值):
Extremes package:base R Documentation
Maxima and Minima
Description:
Returns the (parallel) maxima and minima of the input values.
Usage:
max(..., na.rm = FALSE)
min(..., na.rm = FALSE)
pmax(..., na.rm = FALSE)
pmin(..., na.rm = FALSE)
pmax.int(..., na.rm = FALSE)
pmin.int(..., na.rm = FALSE)
Arguments:
...: numeric or character arguments (see Note).
na.rm: a logical indicating whether missing values should be
removed.
Details:
‘pmax’ and ‘pmin’ take one or more vectors (or matrices) as
arguments and return a single vector giving the ‘parallel’ maxima
(or minima) of the vectors. The first element of the result is
the maximum (minimum) of the first elements of all the arguments,
the second element of the result is the maximum (minimum) of the
second elements of all the arguments and so on. Shorter inputs
are recycled if necessary. ‘attributes’ (such as ‘names’ or
‘dim’) are transferred from the first argument (if applicable).
Here's a version I implemented using Rcpp
.这是我使用
Rcpp
实现的版本。 I compared pmin
with my version, and my version is roughly 3 times faster.我将
pmin
与我的版本进行了比较,我的版本大约快了 3 倍。
library(Rcpp)
cppFunction("
NumericVector min_vec(NumericVector vec1, NumericVector vec2) {
int n = vec1.size();
if(n != vec2.size()) return 0;
else {
NumericVector out(n);
for(int i = 0; i < n; i++) {
out[i] = std::min(vec1[i], vec2[i]);
}
return out;
}
}
")
x1 <- rnorm(100000)
y1 <- rnorm(100000)
microbenchmark::microbenchmark(min_vec(x1, y1))
microbenchmark::microbenchmark(pmin(x1, y1))
x2 <- rnorm(500000)
y2 <- rnorm(500000)
microbenchmark::microbenchmark(min_vec(x2, y2))
microbenchmark::microbenchmark(pmin(x2, y2))
The microbenchmark
function output for 100,000 elements is: 100,000 个元素的微
microbenchmark
函数输出为:
> microbenchmark::microbenchmark(min_vec(x1, y1))
Unit: microseconds
expr min lq mean median uq
min_vec(x1, y1) 215.731 222.3705 230.7018 224.484 228.1115
max neval
284.631 100
> microbenchmark::microbenchmark(pmin(x1, y1))
Unit: microseconds
expr min lq mean median uq max
pmin(x1, y1) 891.486 904.7365 943.5884 922.899 954.873 1098.259
neval
100
And for 500,000 elements:对于 500,000 个元素:
> microbenchmark::microbenchmark(min_vec(x2, y2))
Unit: milliseconds
expr min lq mean median uq
min_vec(x2, y2) 1.493136 2.008122 2.109541 2.140318 2.300022
max neval
2.97674 100
> microbenchmark::microbenchmark(pmin(x2, y2))
Unit: milliseconds
expr min lq mean median uq
pmin(x2, y2) 4.652925 5.146819 5.286951 5.264451 5.445638
max neval
6.639985 100
So you can see the Rcpp
version is faster.所以你可以看到
Rcpp
版本更快。
You could make it better by adding some error checking in the function, for instance: check that both vectors are the same length, or that they are comparable (not character vs. numeric, or boolean vs. numeric).您可以通过在函数中添加一些错误检查来使其更好,例如:检查两个向量的长度是否相同,或者它们是否具有可比性(不是字符与数字,或布尔与数字)。
If your data.frame name is dat.如果您的 data.frame 名称是 dat。
dat$pmin <- do.call(pmin,dat[c("a","b")])
dat$pmax <- do.call(pmax,dat[c("a","b")])
Another possible solution:另一种可能的解决方案:
set.seed(21)
Data <- data.frame(a=runif(10),b=runif(10))
Data$low <- apply(Data[,c("a","b")], 1, min)
Data$high <- apply(Data[,c("a","b")], 1, max)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.