<div dir="ltr"><div><div>I've encountered the following issue iterating over a list of data.tables. </div><div>The issue is only with mapply, not with lapply .</div><div><br></div><div> </div><div>Given a list of data.table's, mapply'ing over the list directly </div>
<div>cannot modify in place. </div><div><br></div><div>Also if attempting to add a new column, we get an "Invalid .internal.selfref" warning. </div><div>Modifying an existing column does not issue a warning, but still fails to modify-in-place</div>
<div><br></div><div>WORKAROUND: </div><div>----------</div><div>The workaround is to iterate over an index to the list, then to </div><div>  modify each data.table via list.of.DTs[[i]][ .. ]</div><div><br></div><div>**Interestingly, this issue occurs with `mapply`, but not `lapply`.**</div>
<div><br></div><div> </div><div>EXAMPLE:</div><div>-------- </div><div>  # Given a list of DT's and two lists of vectors, </div><div>  #   we want to add the corresponding vectors as columns to the DT. </div><div><br>
</div><div>## ---------------- ##</div><div>##   SAMPLE DATA:   ##</div><div>## ---------------- ##</div><div>  # list of data.tables</div><div>  list.DT <- list(</div><div>    DT1=data.table(Col1=111:115, Col2=121:125),</div>
<div>    DT2=data.table(Col1=211:215, Col2=221:225)</div><div>    )</div><div><br></div><div>  # lists of columns to add</div><div>  list.Col3 <- list(131:135, 231:235)</div><div>  list.Col4 <- list(141:145, 241:245)</div>
<div><br></div><div><br></div><div>## ------------------------------------ ##</div><div>##   Iterating over the list elements   ##</div><div>##     adding a new column              ##</div><div>## ------------------------------------ ##</div>
<div>##   Will issue warning and             ##</div><div>##     will fail to modify in place     ##</div><div>## ------------------------------------ ##</div><div>  mapply (</div><div>      function(DT, C3, C4)</div><div>
         DT[, c("Col3", "Col4") := list(C3, C4)],</div><div>      </div><div>      list.DT,  # iterating over the list</div><div>      list.Col3, list.Col4,</div><div>      SIMPLIFY=FALSE</div><div>    ) </div>
<div><br></div><div>  ## Note the lack of change</div><div>  list.DT</div><div><br></div><div><br></div><div>## ------------------------------------ ##</div><div>##   Iterating over an index            ##</div><div>## ------------------------------------ ##</div>
<div>  mapply (</div><div>      function(i, C3, C4)</div><div>         list.DT[[i]] [, c("Col3", "Col4") := list(C3, C4)],</div><div>     </div><div>      seq(list.DT),   # iterating over an index to the list</div>
<div>      list.Col3, list.Col4,</div><div>      SIMPLIFY=FALSE</div><div>    )</div><div><br></div><div>  ## Note each DT _has_ been modified</div><div>  list.DT</div><div><br></div><div>## ------------------------------------ ##</div>
<div>##   Iterating over the list elements   ##</div><div>##     modifying existing column        ##</div><div>## ------------------------------------ ##</div><div>##   No warning issued, but             ##</div><div>##     Will fail to modify in place     ##</div>
<div>## ------------------------------------ ##</div><div>  mapply (</div><div>      function(DT, C3, C4)</div><div>         DT[, c("Col3", "Col4") := list(Col3*1e3, Col4*1e4)],</div><div><br></div><div>
      list.DT,  # iterating over the list</div><div>      list.Col3, list.Col4,</div><div>      SIMPLIFY=FALSE</div><div>    ) </div><div><br></div><div>  ## Note the lack of change (compare with output from `mapply`)</div>
<div>  list.DT</div><div><br></div><div>## ------------------------------------ ##</div><div>##                                      ##</div><div>##   `lapply` works as expected.        ##</div><div>##                                      ##</div>
<div>## ------------------------------------ ##</div><div>  </div><div>  ## NOW WITH lapply</div><div>  lapply(list.DT, </div><div>    function(DT)</div><div>      DT[, newCol := LETTERS[1:5]]</div><div>  )</div><div><br>
</div><div>  ## Note the new column: </div><div>  list.DT</div><div><br></div><div><br></div><div><br></div><div># ========================== # </div><div><br></div><div>##   NON-WORKAROUNDS   ## </div><div>##</div><div>## I also tried all of the following alternatives</div>
<div>##   in hopes of being able to iterate over the list </div><div>##   directly, using `mapply`.  </div><div>## None of these worked. </div><div><br></div><div># (1) Creating the DTs First, then creating the list from them</div>
<div>    DT1 <- data.table(Col1=111:115, Col2=121:125)</div><div>    DT2 <- data.table(Col1=211:215, Col2=221:225)</div><div><br></div><div>    list.DT <- list(DT1=DT1,DT2=DT2 )</div><div><br></div><div><br></div>
<div># (2) Same as 1, and using `copy()` in the call to `list()`</div><div>    list.DT <- list(DT1=copy(DT1), </div><div>                    DT2=copy(DT2) )</div><div><br></div><div># (3) lapply'ing `copy` and then iterating over that list</div>
<div>    list.DT <- lapply(list.DT, copy)</div><div><br></div><div># (4) Not naming the list elements</div><div>    list.DT <- list(DT1, DT2)</div><div>    # and tried</div><div>    list.DT <- list(copy(DT1), copy(DT2))</div>
<div><br></div><div>## All of the above still failed to modify in place</div><div>##   (and also issued the same warning if trying to add a column)</div><div>##    when iterating using mapply</div><div><br></div><div>  mapply(function(DT, C3, C4)</div>
<div>    DT[, c("Col3", "Col4") := list(C3, C4)],</div><div>    list.DT, list.Col3, list.Col4,</div><div>    SIMPLIFY=FALSE)</div><div><br></div><div><br></div><div># ========================== # </div>
</div><div><br></div><br clear="all"><div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)"><div style="font-size:13px">Ricardo Saporta</div><div style="font-size:13px">
Rutgers University, New Jersey<br></div><div style="font-size:13px"><span style="font-size:13px">e: </span><a href="mailto:saporta@rutgers.edu" style="color:rgb(17,85,204);font-size:13px" target="_blank">saporta@rutgers.edu</a></div>
<div><br></div></div></div>
</div>