<div dir="ltr"><div> I submitted the below as bug 4927</div><div><br></div><div>I believe the fix is a simple regex modification, but I dont want to mess with the regex too hastilly and possibly break something.  Would someone care to double check this?</div>
<div><br></div><div>---------------</div><div><br></div><div>Issue:</div><div>----</div><div>Given a data.table with a dot in the column name, using that column name as an argument to `by=` produces different results when the column name is quoted than when it is not. </div>
<div><br></div><div>eg: </div><div><br></div><div>  DT</div><div>     .Col val</div><div>  1:    A   1</div><div>  2:    B   2</div><div><br></div><div>  identical(DT[, sum(val), by=.Col], </div><div>            DT[, sum(val), by=".Col"] )</div>
<div>  # [1] FALSE</div><div><br></div><div><br></div><div>Specifically, if quotes are used NAs are produced in place of the column name.</div><div><br></div><div>Examples follow at the bottom of this email.  I believe the issue is in the regex pattern in a call to `grep` in "[.data.table"</div>
<div><br></div><div>The line is copied and pasted here. </div><div>(currently line 743 in "data.table.r", which is inside "if (any(bynames=="")){..}")</div><div><br></div><div>## ORIGINAL</div>
<div>tt = grep("^eval|^[^[:alpha:] ]",all.vars(bysubl[[jj+1L]],functions=TRUE),invert=TRUE,value=TRUE)[1L]</div><div><br></div><div>## SHOULD (I believe) BE CHANGED TO</div><div>tt = grep("^eval|^[^(\\.|[:alpha:]) ]",all.vars(bysubl[[jj+1L]],functions=TRUE),invert=TRUE,value=TRUE)[1L]</div>
<div>## ... to allow for the name to start with a period. </div><div><br></div><div><br></div><div>## CONTEXT: </div><div>            if (any(bynames=="")) {</div><div>                if (length(bysubl)<2) stop("When 'by' or 'keyby' is list() we expect something inside the brackets")</div>
<div>                for (jj in seq_along(bynames)) {</div><div>                    if (bynames[jj]=="") {</div><div>                        # Best guess. Use "month" in the case of by=month(date), use "a" in the case of by=a%%2</div>
<div>~~~~ THIS LINE ~~~>     tt = grep("^eval|^[^[:alpha:] ]",all.vars(bysubl[[jj+1L]],functions=TRUE),invert=TRUE,value=TRUE)[1L]</div><div>                        if (!length(tt)) tt = all.vars(bysubl[[jj+1L]])[1L]</div>
<div>                        bynames[jj] = tt</div><div>                        # if user doesn't like this inferred name, user has to use by=list() to name the column</div><div>                    }</div><div>                }</div>
<div>            }</div><div><br></div><div>---------------------------------------------------</div><div><br></div><div><br></div><div>EXAMPLE: </div><div><br></div><div>DT <- data.table(.Col = LETTERS[c(1:3, 1:3)], val=1:6)</div>
<div><br></div><div>identical(DT[, sum(val), by=.Col], </div><div>          DT[, sum(val), by=".Col"] )</div><div># [1] FALSE</div><div><br></div><div>## This works as expected</div><div>DT[, sum(val), by=.Col]</div>
<div><br></div><div>   .Col V1</div><div>1:    A  5</div><div>2:    B  7</div><div>3:    C  9</div><div><br></div><div>## Putting the column name within quotes </div><div>##   produces NA in the column names</div><div>DT[, sum(val), by=c(".Col")]</div>
<div>DT[, sum(val), by=".Col"]  # both lines, same output</div><div><br></div><div>   NA V1  <~~~  NOTICE</div><div>1:  A  5</div><div>2:  B  7</div><div>3:  C  9</div><div><br></div><div># notice if we try to use `keyby` we get the following error</div>
<div>DT[, sum(val), keyby=".Col"]</div><div># Error in setkeyv(ans, names(ans)[seq_along(byval)]) : </div><div>#   Column 'NA' is type 'NULL' which is not (currently) allowed as a key column type.</div>
<div><br></div><div>## and this works correctly too</div><div>DT[, sum(val), by=list(.Col=.Col)]</div><div>   .Col V1</div><div>1:    A  5</div><div>2:    B  7</div><div>3:    C  9</div><div><br></div><div>---------------------------------------------------</div>
<div><br></div><div>Only happen with a dot at the start of the name</div><div><br></div><div>## Appears to be only an issue when there is a </div><div>DT2 <- data.table(Col. = LETTERS[c(1:3, 1:3)], val=1:6)</div><div><br>
</div><div>DT2[, sum(val), by=Col.]</div><div>DT2[, sum(val), by=c("Col.")]</div><div><br></div><div>   Col. V1    <~~~ As expected</div><div>1:    A  5</div><div>2:    B  7</div><div>3:    C  9</div><div><br>
</div><div><br></div><div><br></div><div>--</div><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>