Why Use C() to Define Vector

Why use c() to define vector?

Owen's answer is perfect, but one other thing to note is that c() can concatenate more than just vectors.

> x = list(a = rnorm(5), b = rnorm(7))
> y = list(j = rpois(3, 5), k = rpois(4, 2), l = rbinom(9, 1, .43))
> foo = c(x,y)
> foo
$a
[1] 0.280503895 -0.853393705 0.323137905 1.232253725 -0.007638861

$b
[1] -2.0880857 0.2553389 0.9434817 -1.2318130 -0.7011867 0.3931802 -1.6820880

$j
[1] 5 12 5

$k
[1] 3 1 2 1

$l
[1] 1 0 0 1 0 0 1 1 0

> class(foo)
[1] "list"

Second Example:

> x = 1:10
> y = 3*x+rnorm(length(x))
> z = lm(y ~ x)
> is.vector(z)
[1] FALSE
> foo = c(x, z)
> foo
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

[[4]]
[1] 4

[[5]]
[1] 5

[[6]]
[1] 6

[[7]]
[1] 7

[[8]]
[1] 8

[[9]]
[1] 9

[[10]]
[1] 10

$coefficients
(Intercept) x
0.814087 2.813492

$residuals
1 2 3 4 5 6 7
-0.2477695 -0.3375283 -0.1475338 0.5962695 0.5670256 -0.5226752 0.6265995
8 9 10
0.1017986 -0.4425523 -0.1936342

$effects
(Intercept) x
-51.50810097 25.55480795 -0.05371226 0.66592081 0.61250676 -0.50136423

0.62374031 0.07476915 -0.49375185 -0.26900403

$rank
[1] 2

$fitted.values
1 2 3 4 5 6 7 8
3.627579 6.441071 9.254562 12.068054 14.881546 17.695038 20.508529 23.322021
9 10
26.135513 28.949005

$assign
[1] 0 1

$qr
$qr
(Intercept) x
1 -3.1622777 -17.39252713
2 0.3162278 9.08295106
3 0.3162278 0.15621147
4 0.3162278 0.04611510
5 0.3162278 -0.06398128
6 0.3162278 -0.17407766
7 0.3162278 -0.28417403
8 0.3162278 -0.39427041
9 0.3162278 -0.50436679
10 0.3162278 -0.61446316
attr(,"assign")
[1] 0 1

$qraux
[1] 1.316228 1.266308

$pivot
[1] 1 2

$tol
[1] 1e-07

$rank
[1] 2

attr(,"class")
[1] "qr"

$df.residual
[1] 8

$xlevels
named list()

$call
lm(formula = y ~ x)

$terms
y ~ x
attr(,"variables")
list(y, x)
attr(,"factors")
x
y 0
x 1
attr(,"term.labels")
[1] "x"
attr(,"order")
[1] 1
attr(,"intercept")
[1] 1
attr(,"response")
[1] 1
attr(,".Environment")
<environment: R_GlobalEnv>
attr(,"predvars")
list(y, x)
attr(,"dataClasses")
y x
"numeric" "numeric"

$model
y x
1 3.379809 1
2 6.103542 2
3 9.107029 3
4 12.664324 4
5 15.448571 5
6 17.172362 6
7 21.135129 7
8 23.423820 8
9 25.692961 9
10 28.755370 10

What does c do in R?

In R, the c() function returns a vector (a one dimensional array).

In your example:

k <- c(0.5, 1) # k is a vector
k[1] # is 0.5 (remember, R indices start on 1)
k[2] # is 1

If you want to create a vector with 1024 entries (assuming 0.5 increments), you have at least two ways to do it:

# One way
k <- (1:1024) / 2 # this will be 0.5, 1, 1.5, 2, ... , 512
# Another way:
k <- seq(0.5, 512, 0.5)

Also you can use c() to concatenate two vectors:

k <- c(0.5, 1)         # k = 0.5, 1
k <- c(k, 1.5) # k = 0.5, 1, 1.5
k <- c(k, c(2, 2.5)) # k = 0.5, 1, 1.5, 2, 2.5
k <- c(k, k) # k = 0.5, 1, 1.5, 2, 2.5, 0.5, 1, 1.5, 2, 2.5

Please check the help for c() and seq function (in R: ?c and ?seq)


Reference:

  • Quick-R: Data types

Use c() or as.vector() instead warning in R

Note: Don't override R functions, like c. I renamed them for you.

You need to convert the arrays to vectors using as.vector.

Code:

x <- diag(0.5, nrow = 4)

x[lower.tri(x)] <- c(0.2, -0.3, 0.2, 0.5, -0.4, -0.7)

d <- x + t(x)

e <- c(10, 12, 5, 18)

f<- outer(e, e) * d

f
#Defining expected return
mu7 <- c(10, -15, -15, 13)

#Define the value of lambda
labmda7 <- 0.8

#Define the benchmark portfolio weight
b7 <- c(0.2, 0.3, 0.4, 0.1)

#Solving alpha7
i <- c(1, 1, 1, 1)
alpha <- ( t(i) %*% solve(f) %*% mu7) / (t(i) %*% solve(f) %*% i)
alpha <- as.vector(alpha)
xstar7 <- (1 / labmda7) * solve(f) %*% (mu7 - alpha * i )

Or replace the last two lines with:

xstar7 <- (1 / labmda7) * solve(f) %*% (mu7 - as.vector(alpha) * i )

As you can see I write i <- as.vector(i) also alpha <- as.vector(alpha).

And now the output has no warning, output:

     [,1]  [,2] [,3]  [,4]
[1,] 100 24.0 -15 36.0
[2,] 24 144.0 30 -86.4
[3,] -15 30.0 25 -63.0
[4,] 36 -86.4 -63 324.0

C++: Can I define vector within another vector?

Your first example

int a[5];
int *p = &a[1];

does not define an array within another array, it only creates a pointer to an element inside the exisiting array. For standard containers like std::vector the same can be achieved by using iterators:

vector<int> a(5, 0);           // a = [0, 0, 0, 0, 0]
auto iterator = a.begin() + 1; // "points" to a[1]
*iterator = 2; // a = [0, 2, 0, 0, 0]

Iterators are widely used in the standard library and the go-to-solution to provide access to (sub-)ranges of containers.


If you can use C++20 or later you might want to look at std::span instead.

Why is a C++ Vector called a Vector?

Mathematical definition of a vector is a member of the set Sn, which is an ordered sequence of values in a specific set (S). This is what a C++ vector stores.

c++11 variadic programming, how to define a tower of vectors

There is no need for variadics, a recursive typedef is sufficient to generate those types at compile time.


How is is implemented ?

1) Provide a template with 2 arguments : the vector elements type (T), and the desired dimension of the structure (size_t N). Declare a typedef type : it will be based on the declaration of type for the template instantiated with the depth N-1, hence the recursion.

template<typename T, size_t N>
struct VectorGenerator
{
typedef std::vector< typename VectorGenerator<T, N-1>::type > type;
};

2) Provide a termination case for ending the recursion, here a specialization of our template with the dimension 0, declaring the type of a usual std::vector<T>.

template<typename T>
struct VectorGenerator<T, 0>
{
typedef std::vector<T> type;
};

How to use it ?

We can now declare a vector v of type VectorGenerator<T, N>::type :

VectorGenerator<double, 4>::type v; // v as a depth of 4 and handle double

But it's not very readable or convenient, and pretty verbose. Let's introduce new names for our types.

This is the perfect case for template aliasing, with the (C++11) using keyword for aliasing. We have 2 different ways of aliasing :

1) Declare an alias for a particular dimension and type, here we call it V3 for N=3 and T=double :

using V3 = VectorGenerator<double, 3>::type;  // Alias

V3 v; // Use the alias

Or,

2) Declare a template alias for a particular type, leaving the dimension as a template parameter:

template <size_t N> 
using V = typename VectorGenerator<double, N>::type; // Alias

V<3> v; // Use the Alias

Final code sample:

template<typename T, size_t N>
struct VectorGenerator
{
typedef std::vector< typename VectorGenerator<T, N-1>::type > type;
};

template<typename T>
struct VectorGenerator<T, 0>
{
typedef std::vector<T> type;
};

// Alias for V3, V2 ... usage
using V3 = VectorGenerator<double, 3>::type;
using V2 = VectorGenerator<double, 2>::type;

// Alias for V <k> usage
template <size_t N>
using V = typename VectorGenerator<double, N>::type;

int main() {

V<3> v3;
V<2> v2;
v3.push_back(v2);
return 0;
}

Notes :

  • Consider the Boost MultiDimensional Array library.
  • I am not sure of what your final goal is, but this might well be an overkill.
  • As for your second edit, declaring a tuple with multiple vectors of different dimensions is now easy :

Example:

auto tower = std::tuple<V<1>, V<2>, V<3>>(v1, v2, v3);

For the generic tuple generation of multiple "towers", @mpark gave a working C++14 solution, I adapt it here to my code sample:

template <typename T>
struct identity { using type = T; };

// Generate a tuple of towers by mapping index_sequence over gen_tower.
template <typename T, std::size_t... Is>
std::tuple<VectorGenerator<T, Is>...> gen_towers_impl(std::integer_sequence<Is...>);

// Make an index_sequence for N and use gen_towers_impl.
template <typename T, std::size_t N>
struct gen_towers
: identity<decltype(gen_towers_impl<T>(std::make_index_sequence<N>()))> {};

// Convenience type aliases
template <typename T, std::size_t N>
using gen_towers_t = typename gen_towers<T, N>::type;

You will need -std=c++1y to compile it (and include <utility> and <tuple> headers)

See a working example here.



Related Topics



Leave a reply



Submit