How do I name and grow a vector?

Label the elements of a vector, look one up by its ticker, add another on the end, and see why a vector holds only one type.

You name a vector’s elements with names(x) <- or by writing labels inside c(), and you grow it by feeding the old vector back into c() with the new value. Each element can carry a name of its own, so you can ask for a price by its ticker instead of counting positions.

In this lesson I label a vector of prices, look one up by name, add a fourth ticker on the end, and value a portfolio with the names still attached.

Step 1. One name, many values

c() combines values into a vector. length() counts the elements and class() reports the one type they all share.

prices <- c(185.40, 410.20, 128.75)   # three numbers held under one name
print(prices)                         # -> [1] 185.40 410.20 128.75
[1] 185.40 410.20 128.75
print(length(prices))                 # -> [1] 3
[1] 3
print(class(prices))                  # -> [1] "numeric"
[1] "numeric"

Right now the only way to reach the middle price is to know it sits in position 2.

Step 2. Give the elements names

names(x) <- ... attaches one label to each element, in order. R then prints the labels above the values.

names(prices) <- c("AAA", "CCC", "DDD")   # one label per element, same order
print(prices)                                # the labels print above the values
   AAA    CCC    DDD 
185.40 410.20 128.75 
# ->   AAA    CCC    DDD
# -> 185.40 410.20 128.75

You can write the names into c() instead and skip the second step. The result is the same vector.

prices <- c(AAA = 185.40, CCC = 410.20, DDD = 128.75)   # names given as it is built
print(prices)
   AAA    CCC    DDD 
185.40 410.20 128.75 
# ->   AAA    CCC    DDD
# -> 185.40 410.20 128.75

Now a ticker gets you a price. Put the name in square brackets, in quotes.

print(prices["AAA"])              # a ticker in place of a position
  AAA 
185.4 
# ->  AAA
# -> 185.4
print(prices[c("AAA", "DDD")])   # two names at once, in the order I asked for
   AAA    DDD 
185.40 128.75 
# ->   AAA    DDD
# -> 185.40 128.75

A named vector is R’s answer to a Python dictionary: a key gives you a value. The difference is that the value keeps its label. Single brackets return a vector of length one, still named AAA. Double brackets strip the name off and hand back the bare number.

print(prices[["AAA"]])   # -> [1] 185.4
[1] 185.4

names() on its own returns the labels as a character vector, and unname() returns the values without them.

print(names(prices))    # -> [1] "AAA" "CCC" "DDD"
[1] "AAA" "CCC" "DDD"
print(unname(prices))   # -> [1] 185.40 410.20 128.75
[1] 185.40 410.20 128.75

Step 3. Grow it by combining

c() also takes a vector as an argument. Feed it the old vector and one more value, and you get a longer vector back.

prices <- c(prices, BBB = 158.30)   # everything I had, then one more on the end
print(prices)                       # BBB sits at the far right
   AAA    CCC    DDD    BBB 
185.40 410.20 128.75 158.30 
# ->   AAA    CCC    DDD    BBB
# -> 185.40 410.20 128.75 158.30
print(length(prices))               # -> [1] 4
[1] 4

Nothing was changed in place. c() built a new vector and <- put it back under the old name.

Step 4. One type, whatever you feed it

A vector cannot hold a number and a piece of text at the same time. Ask for both and R converts until everything matches.

mixed <- c(1, "a")            # a number and a letter in the same vector
print(mixed)                  # -> [1] "1" "a"
[1] "1" "a"
print(class(mixed))           # -> [1] "character"
[1] "character"

The 1 came back as "1", quotes and all, and class() says the whole vector is text. R converts in one direction only: logical becomes numeric, and numeric becomes text.

print(class(c(1, TRUE)))        # -> [1] "numeric"
[1] "numeric"
print(class(c(1, "a", TRUE)))   # -> [1] "character"
[1] "character"

TRUE next to a number turns into 1. Add any text and the whole vector turns into text, so mixed * 2 would fail.

Step 5. The names travel through the arithmetic

Two named vectors multiply element by element, and the names come out the other side.

shares <- c(AAA = 10, CCC = 4, DDD = 20, BBB = 12)   # one holding per ticker
values <- prices * shares                               # price times shares, position by position
print(values)                                           # four labelled position values
   AAA    CCC    DDD    BBB 
1854.0 1640.8 2575.0 1899.6 
# ->   AAA    CCC    DDD    BBB
# -> 1854.0 1640.8 2575.0 1899.6
print(sum(values))                                      # -> [1] 7969.4
[1] 7969.4

R lines the two vectors up by position, not by name, so shares has to be written in the same order as prices. The names on values come from the first vector.

Because they survived the multiplication, the weights arrive labelled too, and one position can be pulled out by ticker.

weights <- values / sum(values)   # each position as a share of the total
print(round(weights, 3))          # cut to three decimals for reading
  AAA   CCC   DDD   BBB 
0.233 0.206 0.323 0.238 
# ->  AAA   CCC   DDD   BBB
# -> 0.233 0.206 0.323 0.238
print(values["CCC"])
   CCC 
1640.8 
# ->   CCC
# -> 1640.8

Your turn

Build a named vector with AAA at 185.40 and CCC at 410.20. Add FFF at 242.10 on the end. With holdings of 10, 4 and 5 shares, value the portfolio and pull out the FFF position by its name.

prices <- c(AAA = 185.40, CCC = 410.20)   # start with two
prices <- c(prices, FFF = 242.10)          # then combine in the third
print(length(prices))                       # -> [1] 3

shares <- c(AAA = 10, CCC = 4, FFF = 5)  # same order as the prices
values <- prices * shares                   # names carry through
print(values)                               # three labelled position values
# ->   AAA   CCC   FFF
# -> 1854.0 1640.8 1210.5
print(sum(values))                          # -> [1] 4705.3
print(values["FFF"])
# ->   FFF
# -> 1210.5