私はdata.frame
列「a」と「b」。 a列とb列の中で最高と最低を含む「high」と「low」という列を追加したいと思います。
データフレームの行をループせずにこれを行う方法はありますか?
編集:これはOHLCデータ用であるため、高列と低列には、列全体ではなく、同じ行のaとbの間の最高と最低の要素を含める必要があります。これがひどい言い回しならごめんなさい。
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).
これが私がRcpp
を使って実装したバージョンです。 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))
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
そして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
したがって、Rcpp
バージョンの方が高速であることがわかります。
関数にエラーチェックを追加することで、さらに改善できます。たとえば、両方のベクトルが同じ長さであること、または比較可能であることを確認します(文字と数値、またはブール値と数値ではありません)。
別の可能な解決策:
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)
Data.frame名がdatの場合。
dat$pmin <- do.call(pmin,dat[c("a","b")])
dat$pmax <- do.call(pmax,dat[c("a","b")])