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