1

I have a list called tst , reproducible with this dput output below.

structure(list(CAF = structure(list(word = "CAF", freq = structure(list(
    StartDate = structure(1:5, .Label = c("2004-01-04 - 2004-01-10", 
    "2004-01-11 - 2004-01-17", "2004-01-18 - 2004-01-24", "2004-01-25 - 2004-01-31", 
    "2004-02-01 - 2004-02-07"), class = "factor"), RelFreq = c(23L, 
    24L, 26L, 27L, 26L)), .Names = c("StartDate", "RelFreq"), row.names = c(NA, 
5L), class = "data.frame")), .Names = c("word", "freq")), NAV = structure(list(
    word = "NAV", freq = structure(list(StartDate = structure(1:5, .Label = c("2004-01-04 - 2004-01-10", 
    "2004-01-11 - 2004-01-17", "2004-01-18 - 2004-01-24", "2004-01-25 - 2004-01-31", 
    "2004-02-01 - 2004-02-07"), class = "factor"), RelFreq = c(67L, 
    55L, 62L, 79L, 60L)), .Names = c("StartDate", "RelFreq"), row.names = c(NA, 
    5L), class = "data.frame")), .Names = c("word", "freq"))), .Names = c("CAF", 
"NAV"))

For ease of reading, the str output is here

> str(tst)
List of 2
 $ CAF:List of 2
  ..$ word: chr "CAF"
  ..$ freq:'data.frame':    5 obs. of  2 variables:
  .. ..$ StartDate: Factor w/ 5 levels "2004-01-04 - 2004-01-10",..: 1 2 3 4 5
  .. ..$ RelFreq  : int [1:5] 23 24 26 27 26
 $ NAV:List of 2
  ..$ word: chr "NAV"
  ..$ freq:'data.frame':    5 obs. of  2 variables:
  .. ..$ StartDate: Factor w/ 5 levels "2004-01-04 - 2004-01-10",..: 1 2 3 4 5
  .. ..$ RelFreq  : int [1:5] 67 55 62 79 60

I'd like to assign new values to all the StartDate elements nested inside the freq data frame across all list elements. Specifically here, I will be replacing all with the POSIXct date of the first date in the value. (i.e. 2004-01-04 above), though I'm looking for a general solution to apply to other variables in the list that is not reproduced here.

I have a function fun that can do the conversion given a StartDate vector as an input, but I couldn't figure out how to do a batch reassignment across the entire list.

At the moment I resorted to doing a for loop across the entire tst list. Is there a better way, preferrably vectorized?

Ricky
  • 4,616
  • 6
  • 42
  • 72

1 Answers1

1

If you want to retain listness of tst, then

tst2 <- lapply(tst,function(x) { x$freq$StartDate <- as.POSIXct(x$freq$StartDate); x; });
tst2;
## $CAF
## $CAF$word
## [1] "CAF"
##
## $CAF$freq
##    StartDate RelFreq
## 1 2004-01-04      23
## 2 2004-01-11      24
## 3 2004-01-18      26
## 4 2004-01-25      27
## 5 2004-02-01      26
##
##
## $NAV
## $NAV$word
## [1] "NAV"
##
## $NAV$freq
##    StartDate RelFreq
## 1 2004-01-04      67
## 2 2004-01-11      55
## 3 2004-01-18      62
## 4 2004-01-25      79
## 5 2004-02-01      60
##
##
str(tst2);
## List of 2
##  $ CAF:List of 2
##   ..$ word: chr "CAF"
##   ..$ freq:'data.frame':  5 obs. of  2 variables:
##   .. ..$ StartDate: POSIXct[1:5], format: "2004-01-04" "2004-01-11" "2004-01-18" "2004-01-25" ...
##   .. ..$ RelFreq  : int [1:5] 23 24 26 27 26
##  $ NAV:List of 2
##   ..$ word: chr "NAV"
##   ..$ freq:'data.frame':  5 obs. of  2 variables:
##   .. ..$ StartDate: POSIXct[1:5], format: "2004-01-04" "2004-01-11" "2004-01-18" "2004-01-25" ...
##   .. ..$ RelFreq  : int [1:5] 67 55 62 79 60

However, I'd also like to make a recommendation that you transform your data into a data.frame, which would make a lot of operations easier, including this one:

df <- do.call(rbind,lapply(tst,function(x) cbind(Word=x$word,x$freq)));
df$StartDate <- as.POSIXct(df$StartDate);
df;
##       Word  StartDate RelFreq
## CAF.1  CAF 2004-01-04      23
## CAF.2  CAF 2004-01-11      24
## CAF.3  CAF 2004-01-18      26
## CAF.4  CAF 2004-01-25      27
## CAF.5  CAF 2004-02-01      26
## NAV.1  NAV 2004-01-04      67
## NAV.2  NAV 2004-01-11      55
## NAV.3  NAV 2004-01-18      62
## NAV.4  NAV 2004-01-25      79
## NAV.5  NAV 2004-02-01      60
str(df);
## 'data.frame': 10 obs. of  3 variables:
##  $ Word     : Factor w/ 2 levels "CAF","NAV": 1 1 1 1 1 2 2 2 2 2
##  $ StartDate: POSIXct, format: "2004-01-04" "2004-01-11" "2004-01-18" "2004-01-25" ...
##  $ RelFreq  : int  23 24 26 27 26 67 55 62 79 60
Matt
  • 74,352
  • 26
  • 153
  • 180
bgoldst
  • 34,190
  • 6
  • 38
  • 64
  • Thank you! I did try `lapply` earlier, but my mistake was in trying to find a way to assign the value of `x$freq$StartDate` into each individual elements, rather than creating a new list altogether by returning `x`. That was a nifty trick, thanks for sharing. – Ricky May 31 '15 at 03:17
  • @bgoldst: Regarding your duplicate answers. In principle, posting separate standalone answers is fine. However, in this case, your posting a block of code, then a further answer explaining the downsides of the first, and an improvement. That makes the answers non-standalone. – Matt Jul 08 '15 at 20:53
  • @Matt I disagree. My second answer is not merely an "improvement" over the first, it is a completely different answer, and a completely different approach for handling the OP's data. It is quite standalone. The fact that I mentioned my first answer in the second is not significant. I frequently see answerers mention other answers of the same question, perhaps to identify flaws or performance considerations. That doesn't make them non-standalone. But whatever, I accept your deletion+edit. – bgoldst Jul 08 '15 at 21:25
  • Also, @Matt, can you explain why you deleted my answer at http://stackoverflow.com/questions/30552507/r-adding-two-dataframes-different-number-of-rows/30552660? – bgoldst Jul 08 '15 at 21:32
  • @bgoldst: Posting two "answers", one of which is nothing more than a block of uncommented code, and a second which references the first and provides an alternative, is *not* the definition of two standalone answers; largely because the description of one, is in the other. If you edit your blocks of code to be self explanatory, then I'll be more than happy to un-delete them. – Matt Jul 09 '15 at 17:00
  • I'm sorry, I'm not understanding you. For my two answers at http://stackoverflow.com/questions/30552507/r-adding-two-dataframes-different-number-of-rows/30552660, neither answer references the other at all. Neither answer has a description of the other in itself. Both blocks of code are self-explanatory. I've seen answerers give uncommented code blocks as answers many times. I usually give explanations of my code, but I happened not to in those cases, and that certainly doesn't justify deleting them entirely. And they both had upvotes! – bgoldst Jul 09 '15 at 19:27
  • I hope you understand my frustration here. I don't understand why you're spending your time deleting legitimate upvoted answers that have existed for more than a month. – bgoldst Jul 09 '15 at 19:28