Заменить элементы в заданных позициях в arma::vec с соответствующими элементами в другом векторе

Мне было интересно, какой самый компактный синтаксис в Rcpp изменить заданные (несмежные) элементы в позициях pos в векторе v1 с соответствующими элементами в другом векторе (если бы я использовал arma::vec учебный класс)? Скажите, что в РИ будет делать с

v1 = 1:10
pos = c(2,4,10)
v2 = c(3,8,2)
v1[pos] = v2

Это возможно без явного for цикл?

Извиняюсь, если это тривиальный вопрос...

1 ответ

Решение

Я собираюсь ответить на этот вопрос, даже если на него действительно уже ответили в Галерее Rcpp: RcppArmadillo Subsetting post.

Поднабор операций

В броненосце API имеет представления подматриц, которые позволяют выполнять эту операцию.

#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
arma::vec so_subset_params(arma::vec x, arma::uvec pos, arma::vec vals) {
    // Subset and set equal to
    x.elem(pos) = vals;
    return x;
}

/*** R
v1 = 1:10
pos = c(2,4,10)
v2 = c(3,8,2)
so_subset_params(v1, pos-1, v2)    
*/

Это дало бы:

      [,1]
 [1,]    1
 [2,]    3
 [3,]    3
 [4,]    8
 [5,]    5
 [6,]    6
 [7,]    7
 [8,]    8
 [9,]    9
[10,]    2

Репликация кода R в броненосце

Чтобы повторить ваш пример на 100% в броненосце, используйте:

// [[Rcpp::export]]
void so_subset() {

  // --------------- 1:10
  arma::vec v1 = arma::linspace(1,10,10);

  Rcpp::Rcout << "Initial values of V1:" << std::endl << v1 << std::endl;

  // --------------- pos=c(2,4,10)

  // One style to create a subset index
  arma::uvec pos(3);
  pos(0) = 2; pos(1) = 4; pos(2) = 10;

  Rcpp::Rcout << "R indices pos:" << std::endl << pos << std::endl;


  // Adjust for index shift R: [1] => Cpp: [0]
  pos = pos - 1;

  Rcpp::Rcout << "Cpp indices pos:" << std::endl << pos << std::endl;


  // --------------- v2 = c(3,8,2)

  // C++98
  arma::vec v2;
  v2 << 3 << 8 << 2 << arma::endr;

  // C++11
  // arma::vec v2 = { 3, 8, 2}; // requires C++11 plugin

  Rcpp::Rcout << "Replacement values v2:" << std::endl << v2 << std::endl;

  // --------------- v1[pos] = v2

  // Subset and set equal to
  v1.elem(pos) = v2;

  Rcpp::Rcout << "Updated values of v1:" << std::endl << v1 << std::endl;
}

/*** R
so_subset()
*/

Таким образом, вы получите следующий вывод, так как он относится к каждой операции.

Initial values of V1:
    1.0000
    2.0000
    3.0000
    4.0000
    5.0000
    6.0000
    7.0000
    8.0000
    9.0000
   10.0000

R indices pos:
         2
         4
        10

Cpp indices pos:
        1
        3
        9

Replacement values v2:
   3.0000
   8.0000
   2.0000

Updated values of v1:
   1.0000
   3.0000
   3.0000
   8.0000
   5.0000
   6.0000
   7.0000
   8.0000
   9.0000
   2.0000
Другие вопросы по тегам