1

I'm running into an issue applying new names to a list of data frames. I'm using quantmod to pull stock data, and then calculating the 7-Day moving average in this example. I can create the new columns within the list of data frames, but when I go to rename them using lapply and setNames it is only returning the newly renamed column and not any of the old data in each data frame.

require(quantmod)
require(zoo)

# Select Symbols
symbols <- c('AAPL','GOOG')

# Set start Date
start_date <- '2017-01-01'

# Get data and put data xts' into a list. Create empty list and then loop through to add all symbol data
stocks <- list()

for (i in 1:length(symbols)) {
  stocks[[i]] <- getSymbols(symbols[i], src = 'google', from = start_date, auto.assign = FALSE)
}

##### Create the 7 day moving average for each stock in the stocks list #####

stocks <- lapply(stocks, function(x) cbind(x, rollmean(x[,4], 7, align = "right")))

Sample Output:

[[1]]
               AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Close.1
    2017-01-03    115.80    116.33   114.76     116.15    28781865           NA
    2017-01-04    115.85    116.51   115.75     116.02    21118116           NA
    2017-01-05    115.92    116.86   115.81     116.61    22193587           NA
    2017-01-06    116.78    118.16   116.47     117.91    31751900           NA
    2017-01-09    117.95    119.43   117.94     118.99    33561948           NA
    2017-01-10    118.77    119.38   118.30     119.11    24462051           NA
    2017-01-11    118.74    119.93   118.60     119.75    27588593     117.7914
    2017-01-12    118.90    119.30   118.21     119.25    27086220     118.2343
    2017-01-13    119.11    119.62   118.81     119.04    26111948     118.6657

    [[2]]
               GOOG.Open GOOG.High GOOG.Low GOOG.Close GOOG.Volume GOOG.Close.1
    2017-01-03    778.81    789.63   775.80     786.14     1657268           NA
    2017-01-04    788.36    791.34   783.16     786.90     1072958           NA
    2017-01-05    786.08    794.48   785.02     794.02     1335167           NA
    2017-01-06    795.26    807.90   792.20     806.15     1640170           NA
    2017-01-09    806.40    809.97   802.83     806.65     1274645           NA
    2017-01-10    807.86    809.13   803.51     804.79     1176780           NA
    2017-01-11    805.00    808.15   801.37     807.91     1065936     798.9371
    2017-01-12    807.14    807.39   799.17     806.36     1353057     801.8257
    2017-01-13    807.48    811.22   806.69     807.88     1099215     804.8229

I would like to change the "AAPL.Close.1" and "GOOG.Close.1" to say "AAPL.Close.7.Day.MA" and "GOOG.Close.7.Day.MA" respectively (for however many symbols that I choose at the top).

The closest that I've gotten is:

stocks <- lapply(stocks[], function(x) setNames(x[,6], paste0(names(x[,4]), ".7.Day.MA")))

This is correctly naming the new columns, but now my stocks list only contains that single column for each ticker:

[[1]]
           AAPL.Close.7.Day.MA
2017-01-03                  NA
2017-01-04                  NA
2017-01-05                  NA
2017-01-06                  NA
2017-01-09                  NA
2017-01-10                  NA
2017-01-11            117.7914
2017-01-12            118.2343
2017-01-13            118.6657

[[2]]
           GOOG.Close.7.Day.MA
2017-01-03                  NA
2017-01-04                  NA
2017-01-05                  NA
2017-01-06                  NA
2017-01-09                  NA
2017-01-10                  NA
2017-01-11            798.9371
2017-01-12            801.8257
2017-01-13            804.8229

Why is the setNames function removing the original columns?

zx8754
  • 52,746
  • 12
  • 114
  • 209
Jason J
  • 110
  • 2
  • 7

1 Answers1

2

Almost there:

N = 10 #number of pseudorandom numbers
df1 <- data.frame(a=runif(N),b=sample(N))#1st data frame
df2 <- data.frame(c=rnorm(N),google=df1$b^2,e=df1$a^3)#2nd data frame
stocks<-list(df1,df2)# create the list

lapply(stocks,names) # get the names of each list element (data.frame) 
[[1]]
[1] "a" "b"

[[2]]
[1] "c"      "google" "e"     

Since we are using a function we need to use the <<- in order to overwrite the initial object stocks.

lapply(seq_along(1:length(stocks)),function(x) names(stocks[[x]])<<-gsub(pattern = "google",replacement = "google2",x=names(stocks[[x]])))#replacing the string google 

[[1]]
[1] "a" "b"

[[2]]
[1] "c"       "google2" "e"      

Additionally (verification) stocks contains the new names:

> stocks
[[1]]
            a  b
 1  0.73826897  3
 2  0.35627664  8
 3  0.89060134  7
 4  0.72629312 10
 5  0.97069742  4  
 6  0.12530931  2
 7  0.65744257  9
 8  0.06218019  1
 9  0.67322891  6
 10 0.66128204  5

 [[2]]
             c google2           e
 1  -0.5272267       9 0.402386917
 2   0.6993945      64 0.045223278
 3   0.3707304      49 0.706398932
 4  -0.2371541     100 0.383120861
 5   1.5073834      16 0.914643019
 6   0.4098821       4 0.001967660
 7  -0.3014211      81 0.284166886
 8   0.3248919       1 0.000240412
 9   1.2757740      36 0.305132358
 10  1.5938208      25 0.289174620
amonk
  • 1,769
  • 2
  • 18
  • 27
  • Thanks! gsub looks to work well here. I'm still not sure why my original code removed all of the columns that weren't affected though. Can you explain why? – Jason J Jun 27 '17 at 01:21
  • Check this out: https://stackoverflow.com/questions/6081439/changing-column-names-of-a-data-frame-in-r – amonk Jun 27 '17 at 06:51