You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
if (!is.atomic(lhs)) stopf("LHS of := must be a symbol, or an atomic vector (column names or positions).")
1151
-
if (is.character(lhs)) {
1152
-
m= chmatch(lhs, names_x)
1153
-
} elseif (is.numeric(lhs)) {
1154
-
m= as.integer(lhs)
1155
-
if (any(m<1L| ncol(x)<m)) stopf("LHS of := appears to be column positions but are outside [1,ncol] range. New columns can only be added by name.")
1156
-
lhs=names_x[m]
1157
-
} else
1158
-
stopf("LHS of := isn't column names ('character') or positions ('integer' or 'numeric')")
1159
-
if (!anyNA(m)) {
1160
-
# updates by reference to existing columns
1161
-
cols= as.integer(m)
1162
-
newnames=NULL
1163
-
if (identical(irows, integer())) {
1164
-
# Empty integer() means no rows e.g. logical i with only FALSE and NA
1165
-
# got converted to empty integer() by the which() above
1166
-
# Short circuit and do-nothing since columns already exist. If some don't
1167
-
# exist then for consistency with cases where irows is non-empty, we need to create
1168
-
# them of the right type and populate with NA. Which will happen via the regular
1169
-
# alternative branches below, to cover #759.
1170
-
# We need this short circuit at all just for convenience. Otherwise users may need to
1171
-
# fix errors in their RHS when called on empty edge cases, even when the result won't be
1172
-
# used anyway (so it would be annoying to have to fix it.)
1173
-
if (verbose) {
1174
-
catf("No rows match i. No new columns to add so not evaluating RHS of :=\nAssigning to 0 row subset of %d rows\n", nrow(x))
1175
-
}
1176
-
.Call(Cassign, x, irows, NULL, NULL, NULL) # only purpose is to write 0 to .Last.updated
1177
-
.global$print= address(x)
1178
-
return(invisible(x))
1179
-
}
1180
-
} else {
1181
-
# Adding new column(s). TO DO: move after the first eval in case the jsub has an error.
1182
-
newnames=setdiff(lhs, names_x)
1183
-
m[is.na(m)] = ncol(x)+seq_along(newnames)
1184
-
cols= as.integer(m)
1185
-
# don't pass verbose to selfrefok here -- only activated when
1186
-
# ok=-1 which will trigger setalloccol with verbose in the next
1187
-
# branch, which again calls _selfrefok and returns the message then
1188
-
if ((ok<-selfrefok(x, verbose=FALSE))==0L) # ok==0 so no warning when loaded from disk (-1) [-1 considered TRUE by R]
1189
-
if (is.data.table(x)) warningf("A shallow copy of this data.table was taken so that := can add or remove %d columns by reference. At an earlier point, this data.table was copied by R (or was created manually using structure() or similar). Avoid names<- and attr<- which in R currently (and oddly) may copy the whole data.table. Use set* syntax instead to avoid copying: ?set, ?setnames and ?setattr. It's also not unusual for data.table-agnostic packages to produce tables affected by this issue. If this message doesn't help, please report your use case to the data.table issue tracker so the root cause can be fixed or this message improved.", length(newnames))
1190
-
# !is.data.table for DF |> DT(,:=) tests 2212.16-19 (#5113) where a shallow copy is routine for data.frame
1191
-
if ((ok<1L) || (truelength(x) < ncol(x)+length(newnames))) {
1192
-
DT=x# in case getOption contains "ncol(DT)" as it used to. TODO: warn and then remove
1193
-
n= length(newnames) + eval(getOption("datatable.alloccol")) # TODO: warn about expressions and then drop the eval()
1194
-
# i.e. reallocate at the size as if the new columns were added followed by setalloccol().
1195
-
name= substitute(x)
1196
-
if (is.name(name) &&ok&&verbose) { # && NAMED(x)>0 (TO DO) # ok here includes -1 (loaded from disk)
1197
-
catf("Growing vector of column pointers from truelength %d to %d. A shallow copy has been taken, see ?setalloccol. Only a potential issue if two variables point to the same data (we can't yet detect that well) and if not you can safely ignore this. To avoid this message you could setalloccol() first, deep copy first using copy(), wrap with suppressWarnings() or increase the 'datatable.alloccol' option.\n", truelength(x), n)
1198
-
# #1729 -- copying to the wrong environment here can cause some confusion
1199
-
if (ok==-1L) catf("Note that the shallow copy will assign to the environment from which := was called. That means for example that if := was called within a function, the original table may be unaffected.\n")
1200
-
1201
-
# Verbosity should not issue warnings, so cat rather than warning.
1202
-
# TO DO: Add option 'datatable.pedantic' to turn on warnings like this.
1203
-
1204
-
# TO DO ... comments moved up from C ...
1205
-
# Note that the NAMED(dt)>1 doesn't work because .Call
1206
-
# always sets to 2 (see R-ints), it seems. Work around
1207
-
# may be possible but not yet working. When the NAMED test works, we can drop allocwarn argument too
1208
-
# because that's just passed in as FALSE from [<- where we know `*tmp*` isn't really NAMED=2.
1209
-
# Note also that this growing will happen for missing columns assigned NULL, too. But so rare, we
1210
-
# don't mind.
1211
-
}
1212
-
setalloccol(x, n, verbose=verbose) # always assigns to calling scope; i.e. this scope
if (!is.atomic(lhs)) stopf("LHS of := must be a symbol, or an atomic vector (column names or positions).")
1152
+
if (is.character(lhs)) {
1153
+
m= chmatch(lhs, names_x)
1154
+
} elseif (is.numeric(lhs)) {
1155
+
m= as.integer(lhs)
1156
+
if (any(m<1L| ncol(x)<m)) stopf("LHS of := appears to be column positions but are outside [1,ncol] range. New columns can only be added by name.")
1157
+
lhs=names_x[m]
1158
+
} else
1159
+
stopf("LHS of := isn't column names ('character') or positions ('integer' or 'numeric')")
1160
+
1161
+
if (!anyNA(m)) {
1162
+
# updates by reference to existing columns
1163
+
cols= as.integer(m)
1164
+
newnames=NULL
1165
+
if (identical(irows, integer())) {
1166
+
# Empty integer() means no rows e.g. logical i with only FALSE and NA
1167
+
# got converted to empty integer() by the which() above
1168
+
# Short circuit and do-nothing since columns already exist. If some don't
1169
+
# exist then for consistency with cases where irows is non-empty, we need to create
1170
+
# them of the right type and populate with NA. Which will happen via the regular
1171
+
# alternative branches below, to cover #759.
1172
+
# We need this short circuit at all just for convenience. Otherwise users may need to
1173
+
# fix errors in their RHS when called on empty edge cases, even when the result won't be
1174
+
# used anyway (so it would be annoying to have to fix it.)
1175
+
if (verbose) {
1176
+
catf("No rows match i. No new columns to add so not evaluating RHS of :=\nAssigning to 0 row subset of %d rows\n", nrow(x))
1177
+
}
1178
+
.Call(Cassign, x, irows, NULL, NULL, NULL) # only purpose is to write 0 to .Last.updated
1179
+
.global$print= address(x)
1180
+
return(invisible(x))
1181
+
}
1182
+
} else {
1183
+
# Adding new column(s). TO DO: move after the first eval in case the jsub has an error.
1184
+
newnames= setdiff(lhs, names_x)
1185
+
m[is.na(m)] = ncol(x) + seq_along(newnames)
1186
+
cols= as.integer(m)
1187
+
# don't pass verbose to selfrefok here -- only activated when
1188
+
# ok=-1 which will trigger setalloccol with verbose in the next
1189
+
# branch, which again calls _selfrefok and returns the message then
1190
+
if ((ok<- selfrefok(x, verbose=FALSE)) ==0L) { # ok==0 so no warning when loaded from disk (-1) [-1 considered TRUE by R]
1191
+
if (is.data.table(x)) warningf("A shallow copy of this data.table was taken so that := can add or remove %d columns by reference. At an earlier point, this data.table was copied by R (or was created manually using structure() or similar). Avoid names<- and attr<- which in R currently (and oddly) may copy the whole data.table. Use set* syntax instead to avoid copying: ?set, ?setnames and ?setattr. It's also not unusual for data.table-agnostic packages to produce tables affected by this issue. If this message doesn't help, please report your use case to the data.table issue tracker so the root cause can be fixed or this message improved.", length(newnames))
1192
+
# !is.data.table for DF |> DT(,:=) tests 2212.16-19 (#5113) where a shallow copy is routine for data.frame
1193
+
}
1194
+
if ((ok<1L) || (truelength(x) < ncol(x) + length(newnames))) {
1195
+
DT=x# in case getOption contains "ncol(DT)" as it used to. TODO: warn and then remove
1196
+
n= length(newnames) + eval(getOption("datatable.alloccol")) # TODO: warn about expressions and then drop the eval()
1197
+
# i.e. reallocate at the size as if the new columns were added followed by setalloccol().
1198
+
name= substitute(x)
1199
+
if (is.name(name) &&ok&&verbose) { # && NAMED(x)>0 (TO DO) # ok here includes -1 (loaded from disk)
1200
+
catf("Growing vector of column pointers from truelength %d to %d. A shallow copy has been taken, see ?setalloccol. Only a potential issue if two variables point to the same data (we can't yet detect that well) and if not you can safely ignore this. To avoid this message you could setalloccol() first, deep copy first using copy(), wrap with suppressWarnings() or increase the 'datatable.alloccol' option.\n", truelength(x), n)
1201
+
# #1729 -- copying to the wrong environment here can cause some confusion
1202
+
if (ok==-1L) catf("Note that the shallow copy will assign to the environment from which := was called. That means for example that if := was called within a function, the original table may be unaffected.\n")
1203
+
# Verbosity should not issue warnings, so cat rather than warning.
1204
+
# TO DO: Add option 'datatable.pedantic' to turn on warnings like this.
1205
+
# TO DO ... comments moved up from C ...
1206
+
# Note that the NAMED(dt)>1 doesn't work because .Call
1207
+
# always sets to 2 (see R-ints), it seems. Work around
1208
+
# may be possible but not yet working. When the NAMED test works, we can drop allocwarn argument too
1209
+
# because that's just passed in as FALSE from [<- where we know `*tmp*` isn't really NAMED=2.
1210
+
# Note also that this growing will happen for missing columns assigned NULL, too. But so rare, we
1211
+
# don't mind.
1212
+
}
1213
+
setalloccol(x, n, verbose=verbose) # always assigns to calling scope; i.e. this scope
stopf("Cannot assign to an under-allocated recursively indexed list -- L[[i]][,:=] syntax is only valid when i is length 1, but its length is %d", length(j))
3459
+
}
3460
+
3461
+
j= match(j, names(k))
3462
+
if (is.na(j)) {
3463
+
if (error_on_missing) {
3464
+
stopf("Item '%s' not found in names of input list", origj)
3465
+
} else {
3466
+
internal_error("item '%s' not found in names of list", origj) # nocov
0 commit comments