Search code examples
r

Two non-identical lists but can't find where the difference is in R


I tried to replace some elements in list a with another elements B1 or B2 in R. That uses function f to generate a new list c. However, when I manually replace the elements by creating a list d, the new list c is different from d, even though both look the same.

a <- list(~X1, ~X2 + C1 + X1*C1)
b <- list(~X1, ~X2 + X3)

f <- \(nms, replacement) {
 replacement <- paste0(replacement, seq_along(nms))
 Map(\(nms, replacement) {
   vars <- all.vars(nms)
   setNames(lapply(rep(replacement, length(vars)), as.name), vars)
 }, nms, replacement) |>
  unlist()
}

c <- lapply(a, \(x) do.call(substitute, list(x, f(b, "B"))))
d <- list(~B1, ~B2 + C1 + B1*C1)

When I check if c and d are identical, it returns that they are not the same:

identical(c,d)

[1] FALSE

But I can't find where the different elements lie in

c[!c %in% d]

list()

I am very confused about what the different elements are. By directly looking at c and d, they seem to be the same. I really need to keep function f to do the element replacement, but have to ensure c and d are essentially the same.

A follow-up question, the reason why the previous problem is concerning is because, if I use list c to draw a matrix, it will fail. But if I use d, manually created list, it works.

B1 <- rnorm(100)
B2 <- rnorm(100, mean = 2)
C1 <- rbinom(100, size = 1, prob = 0.5)
data <- data.frame(cbind(B1, B2, C1))

model.matrix(d[[2]], model.frame(d[[2]], data, na.action = 'na.pass'))
model.matrix(c[[2]], model.frame(c[[2]], data, na.action = 'na.pass'))

Error in x$terms %||% attr(x, "terms") %||% stop("no terms component nor attribute") : no terms component nor attribute

This error message was incurred from list c, but for list d, no error occurred.


Solution

  • They're not identical but they are 'equal', so there's no difference to find, e.g.

    a <- list(~X1, ~X2 + C1 + X1*C1)
    b <- list(~X1, ~X2 + X3)
    
    f <- \(nms, replacement) {
      replacement <- paste0(replacement, seq_along(nms))
      Map(\(nms, replacement) {
        vars <- all.vars(nms)
        setNames(lapply(rep(replacement, length(vars)), as.name), vars)
      }, nms, replacement) |>
        unlist()
    }
    
    c <- lapply(a, \(x) do.call(substitute, list(x, f(b, "B"))))
    d <- list(~B1, ~B2 + C1 + B1*C1)
    
    identical(c,d)
    #> [1] FALSE
    str(c)
    #> List of 2
    #>  $ : language ~B1
    #>  $ : language ~B2 + C1 + B1 * C1
    str(d)
    #> List of 2
    #>  $ :Class 'formula'  language ~B1
    #>   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
    #>  $ :Class 'formula'  language ~B2 + C1 + B1 * C1
    #>   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
    
    all.equal(c,d)
    #> [1] TRUE
    

    Created on 2024-09-09 with reprex v2.1.0

    The difference highlighted by str() is causing your issue with model.matrix() (in the 'follow up' section). If you pass c[[2]] as a formula it works as expected, e.g.

    a <- list(~X1, ~X2 + C1 + X1*C1)
    b <- list(~X1, ~X2 + X3)
    
    f <- \(nms, replacement) {
      replacement <- paste0(replacement, seq_along(nms))
      Map(\(nms, replacement) {
        vars <- all.vars(nms)
        setNames(lapply(rep(replacement, length(vars)), as.name), vars)
      }, nms, replacement) |>
        unlist()
    }
    
    c <- lapply(a, \(x) do.call(substitute, list(x, f(b, "B"))))
    d <- list(~B1, ~B2 + C1 + B1*C1)
    
    identical(c,d)
    #> [1] FALSE
    str(c)
    #> List of 2
    #>  $ : language ~B1
    #>  $ : language ~B2 + C1 + B1 * C1
    str(d)
    #> List of 2
    #>  $ :Class 'formula'  language ~B1
    #>   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
    #>  $ :Class 'formula'  language ~B2 + C1 + B1 * C1
    #>   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
    
    all.equal(c,d)
    #> [1] TRUE
    
    B1 <- rnorm(100)
    B2 <- rnorm(100, mean = 2)
    C1 <- rbinom(100, size = 1, prob = 0.5)
    data <- data.frame(cbind(B1, B2, C1))
    
    model.matrix(d[[2]], model.frame(d[[2]], data, na.action = 'na.pass'))
    #>     (Intercept)           B2 C1          B1       C1:B1
    #> 1             1  3.093556617  1 -0.78860541 -0.78860541
    #> 2             1  1.886026799  0  0.56973224  0.00000000
    #> 3             1  2.673870066  1 -0.60595212 -0.60595212
    #> 4             1  1.871221289  0 -0.94427123  0.00000000
    #> 5             1  0.921999097  0 -1.69236771  0.00000000
    #> 6             1  2.075295923  1  0.10612483  0.10612483
    #> 7             1  2.460368025  1  1.27639862  1.27639862
    #> 8             1  4.009522227  0  0.39725422  0.00000000
    #> 9             1  2.223665025  1 -0.67107557 -0.67107557
    #> 10            1  3.618806953  1  0.21343146  0.21343146
    #> 11            1  3.307040111  1 -1.25317583 -1.25317583
    #> 12            1  3.941725053  0 -0.69040161  0.00000000
    #> 13            1  3.111269308  1  0.55712532  0.55712532
    #> 14            1  2.132800352  1  0.79852880  0.79852880
    #> 15            1  1.454812161  1  0.18188305  0.18188305
    #> 16            1  4.326464313  1 -0.11846250 -0.11846250
    #> 17            1  1.302022850  0 -0.87418884  0.00000000
    #> 18            1  0.583680486  1 -0.53905498 -0.53905498
    #> 19            1  0.635689127  0  1.19463088  0.00000000
    #> 20            1  3.054064555  0  0.54188247  0.00000000
    #> 21            1  1.539410493  1  1.52761448  1.52761448
    #> 22            1  3.674028603  0  0.37046407  0.00000000
    #> 23            1  3.700911590  1  0.67188467  0.67188467
    #> 24            1  2.634141310  0  0.57403657  0.00000000
    #> 25            1  2.966272829  1  0.30644870  0.30644870
    #> 26            1  2.332830222  1  0.32473422  0.32473422
    #> 27            1  1.540861739  1  1.40447120  1.40447120
    #> 28            1 -0.940790234  0  1.69992443  0.00000000
    #> 29            1  3.290360051  1  0.09498966  0.09498966
    #> 30            1  2.650609034  0  0.77487189  0.00000000
    #> 31            1  2.303463420  0  1.53959759  0.00000000
    #> 32            1  1.053506147  0  0.73908997  0.00000000
    #> 33            1  1.426712923  0 -0.16465926  0.00000000
    #> 34            1 -0.201379101  0 -0.38726197  0.00000000
    #> 35            1  0.001141829  0 -0.58938402  0.00000000
    #> 36            1  0.375382810  1  1.26362046  1.26362046
    #> 37            1  1.206842118  0 -0.61859053  0.00000000
    #> 38            1  1.834290474  1 -0.42452583 -0.42452583
    #> 39            1  0.846476578  1 -1.81057200 -1.81057200
    #> 40            1  1.330010557  1  0.34031947  0.34031947
    #> 41            1  2.124938389  1 -1.12457154 -1.12457154
    #> 42            1  2.023037941  1  1.32196017  1.32196017
    #> 43            1  2.129205146  0 -0.95367504  0.00000000
    #> 44            1  4.724999255  0 -0.36177523  0.00000000
    #> 45            1  3.487162408  1  1.11070383  1.11070383
    #> 46            1  2.553726607  0  0.69837652  0.00000000
    #> 47            1  3.050741904  0 -0.67757336  0.00000000
    #> 48            1  3.554602933  0  0.36333151  0.00000000
    #> 49            1  2.748949526  0  0.87355033  0.00000000
    #> 50            1  1.026679772  1  1.14239462  1.14239462
    #> 51            1  1.345758771  1 -1.32579950 -1.32579950
    #> 52            1  3.360090558  1 -0.99770094 -0.99770094
    #> 53            1  3.150835981  0 -0.91257389  0.00000000
    #> 54            1  3.217728895  1 -0.77698461 -0.77698461
    #> 55            1  2.312442115  0  0.27581649  0.00000000
    #> 56            1  0.699403756  1  1.94805079  1.94805079
    #> 57            1  0.770966838  1  1.47982081  1.47982081
    #> 58            1  1.211283624  1  0.40359669  0.40359669
    #> 59            1  3.251803657  1  0.40494923  0.40494923
    #> 60            1  0.558543700  0 -0.33612244  0.00000000
    #> 61            1  2.339337168  1  0.78301829  0.78301829
    #> 62            1  1.558130647  0 -1.15495472  0.00000000
    #> 63            1  2.790130444  1 -1.35876495 -1.35876495
    #> 64            1  1.337390342  0  0.17752648  0.00000000
    #> 65            1  1.033420092  0 -2.29789756  0.00000000
    #> 66            1 -0.321807848  1 -1.93711695 -1.93711695
    #> 67            1  1.958510332  1 -0.63353430 -0.63353430
    #> 68            1  2.281820149  0 -1.08199237  0.00000000
    #> 69            1  3.035093868  1  0.26209777  0.26209777
    #> 70            1  2.851736534  1 -0.56065301 -0.56065301
    #> 71            1  2.007729850  0  0.23194564  0.00000000
    #> 72            1  2.155800998  0  0.62628023  0.00000000
    #> 73            1  1.162590867  0  0.81750230  0.00000000
    #> 74            1  1.721310695  0 -1.28561868  0.00000000
    #> 75            1  2.839788378  0 -0.86662818  0.00000000
    #> 76            1  2.059912681  0 -1.89798538  0.00000000
    #> 77            1  2.282398919  1  1.73596974  1.73596974
    #> 78            1  2.565795767  1 -0.12856807 -0.12856807
    #> 79            1  2.572737178  0 -0.51742529  0.00000000
    #> 80            1  0.533060826  0  1.01470751  0.00000000
    #> 81            1  2.303617594  0  0.08326794  0.00000000
    #> 82            1  2.710917777  0 -2.59741216  0.00000000
    #> 83            1  1.397209217  1 -2.37363088 -2.37363088
    #> 84            1  2.140376061  1 -0.90394275 -0.90394275
    #> 85            1  1.391443923  0 -0.99545878  0.00000000
    #> 86            1  2.697787502  1  1.31235291  1.31235291
    #> 87            1  1.070710761  1 -0.32742765 -0.32742765
    #> 88            1  1.725460871  0 -0.20906359  0.00000000
    #> 89            1  2.245153738  1 -0.48761022 -0.48761022
    #> 90            1  0.987976417  0  1.04495976  0.00000000
    #> 91            1  0.230881185  1 -0.26202523 -0.26202523
    #> 92            1  2.751294035  0  0.42203115  0.00000000
    #> 93            1  2.023670252  1  0.21725446  0.21725446
    #> 94            1  2.508597779  0 -0.34738879  0.00000000
    #> 95            1  1.682285681  0 -0.44146421  0.00000000
    #> 96            1  1.584391454  1  1.93577488  1.93577488
    #> 97            1  1.831828815  0 -1.09342683  0.00000000
    #> 98            1  1.657436050  0  0.44482820  0.00000000
    #> 99            1  2.378333477  0 -0.44507681  0.00000000
    #> 100           1  2.959965426  1  0.03676946  0.03676946
    #> attr(,"assign")
    #> [1] 0 1 2 3 4
    str(d[[2]])
    #> Class 'formula'  language ~B2 + C1 + B1 * C1
    #>   ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
    model.matrix(c[[2]], model.frame(c[[2]], data, na.action = 'na.pass'))
    #> Error in x$terms %||% attr(x, "terms") %||% stop("no terms component nor attribute"): no terms component nor attribute
    str(c[[2]])
    #>  language ~B2 + C1 + B1 * C1
    
    model.matrix(as.formula(c[[2]]), model.frame(c[[2]], data, na.action = 'na.pass'))
    #>     (Intercept)           B2 C1          B1       C1:B1
    #> 1             1  3.093556617  1 -0.78860541 -0.78860541
    #> 2             1  1.886026799  0  0.56973224  0.00000000
    #> 3             1  2.673870066  1 -0.60595212 -0.60595212
    #> 4             1  1.871221289  0 -0.94427123  0.00000000
    #> 5             1  0.921999097  0 -1.69236771  0.00000000
    #> 6             1  2.075295923  1  0.10612483  0.10612483
    #> 7             1  2.460368025  1  1.27639862  1.27639862
    #> 8             1  4.009522227  0  0.39725422  0.00000000
    #> 9             1  2.223665025  1 -0.67107557 -0.67107557
    #> 10            1  3.618806953  1  0.21343146  0.21343146
    #> 11            1  3.307040111  1 -1.25317583 -1.25317583
    #> 12            1  3.941725053  0 -0.69040161  0.00000000
    #> 13            1  3.111269308  1  0.55712532  0.55712532
    #> 14            1  2.132800352  1  0.79852880  0.79852880
    #> 15            1  1.454812161  1  0.18188305  0.18188305
    #> 16            1  4.326464313  1 -0.11846250 -0.11846250
    #> 17            1  1.302022850  0 -0.87418884  0.00000000
    #> 18            1  0.583680486  1 -0.53905498 -0.53905498
    #> 19            1  0.635689127  0  1.19463088  0.00000000
    #> 20            1  3.054064555  0  0.54188247  0.00000000
    #> 21            1  1.539410493  1  1.52761448  1.52761448
    #> 22            1  3.674028603  0  0.37046407  0.00000000
    #> 23            1  3.700911590  1  0.67188467  0.67188467
    #> 24            1  2.634141310  0  0.57403657  0.00000000
    #> 25            1  2.966272829  1  0.30644870  0.30644870
    #> 26            1  2.332830222  1  0.32473422  0.32473422
    #> 27            1  1.540861739  1  1.40447120  1.40447120
    #> 28            1 -0.940790234  0  1.69992443  0.00000000
    #> 29            1  3.290360051  1  0.09498966  0.09498966
    #> 30            1  2.650609034  0  0.77487189  0.00000000
    #> 31            1  2.303463420  0  1.53959759  0.00000000
    #> 32            1  1.053506147  0  0.73908997  0.00000000
    #> 33            1  1.426712923  0 -0.16465926  0.00000000
    #> 34            1 -0.201379101  0 -0.38726197  0.00000000
    #> 35            1  0.001141829  0 -0.58938402  0.00000000
    #> 36            1  0.375382810  1  1.26362046  1.26362046
    #> 37            1  1.206842118  0 -0.61859053  0.00000000
    #> 38            1  1.834290474  1 -0.42452583 -0.42452583
    #> 39            1  0.846476578  1 -1.81057200 -1.81057200
    #> 40            1  1.330010557  1  0.34031947  0.34031947
    #> 41            1  2.124938389  1 -1.12457154 -1.12457154
    #> 42            1  2.023037941  1  1.32196017  1.32196017
    #> 43            1  2.129205146  0 -0.95367504  0.00000000
    #> 44            1  4.724999255  0 -0.36177523  0.00000000
    #> 45            1  3.487162408  1  1.11070383  1.11070383
    #> 46            1  2.553726607  0  0.69837652  0.00000000
    #> 47            1  3.050741904  0 -0.67757336  0.00000000
    #> 48            1  3.554602933  0  0.36333151  0.00000000
    #> 49            1  2.748949526  0  0.87355033  0.00000000
    #> 50            1  1.026679772  1  1.14239462  1.14239462
    #> 51            1  1.345758771  1 -1.32579950 -1.32579950
    #> 52            1  3.360090558  1 -0.99770094 -0.99770094
    #> 53            1  3.150835981  0 -0.91257389  0.00000000
    #> 54            1  3.217728895  1 -0.77698461 -0.77698461
    #> 55            1  2.312442115  0  0.27581649  0.00000000
    #> 56            1  0.699403756  1  1.94805079  1.94805079
    #> 57            1  0.770966838  1  1.47982081  1.47982081
    #> 58            1  1.211283624  1  0.40359669  0.40359669
    #> 59            1  3.251803657  1  0.40494923  0.40494923
    #> 60            1  0.558543700  0 -0.33612244  0.00000000
    #> 61            1  2.339337168  1  0.78301829  0.78301829
    #> 62            1  1.558130647  0 -1.15495472  0.00000000
    #> 63            1  2.790130444  1 -1.35876495 -1.35876495
    #> 64            1  1.337390342  0  0.17752648  0.00000000
    #> 65            1  1.033420092  0 -2.29789756  0.00000000
    #> 66            1 -0.321807848  1 -1.93711695 -1.93711695
    #> 67            1  1.958510332  1 -0.63353430 -0.63353430
    #> 68            1  2.281820149  0 -1.08199237  0.00000000
    #> 69            1  3.035093868  1  0.26209777  0.26209777
    #> 70            1  2.851736534  1 -0.56065301 -0.56065301
    #> 71            1  2.007729850  0  0.23194564  0.00000000
    #> 72            1  2.155800998  0  0.62628023  0.00000000
    #> 73            1  1.162590867  0  0.81750230  0.00000000
    #> 74            1  1.721310695  0 -1.28561868  0.00000000
    #> 75            1  2.839788378  0 -0.86662818  0.00000000
    #> 76            1  2.059912681  0 -1.89798538  0.00000000
    #> 77            1  2.282398919  1  1.73596974  1.73596974
    #> 78            1  2.565795767  1 -0.12856807 -0.12856807
    #> 79            1  2.572737178  0 -0.51742529  0.00000000
    #> 80            1  0.533060826  0  1.01470751  0.00000000
    #> 81            1  2.303617594  0  0.08326794  0.00000000
    #> 82            1  2.710917777  0 -2.59741216  0.00000000
    #> 83            1  1.397209217  1 -2.37363088 -2.37363088
    #> 84            1  2.140376061  1 -0.90394275 -0.90394275
    #> 85            1  1.391443923  0 -0.99545878  0.00000000
    #> 86            1  2.697787502  1  1.31235291  1.31235291
    #> 87            1  1.070710761  1 -0.32742765 -0.32742765
    #> 88            1  1.725460871  0 -0.20906359  0.00000000
    #> 89            1  2.245153738  1 -0.48761022 -0.48761022
    #> 90            1  0.987976417  0  1.04495976  0.00000000
    #> 91            1  0.230881185  1 -0.26202523 -0.26202523
    #> 92            1  2.751294035  0  0.42203115  0.00000000
    #> 93            1  2.023670252  1  0.21725446  0.21725446
    #> 94            1  2.508597779  0 -0.34738879  0.00000000
    #> 95            1  1.682285681  0 -0.44146421  0.00000000
    #> 96            1  1.584391454  1  1.93577488  1.93577488
    #> 97            1  1.831828815  0 -1.09342683  0.00000000
    #> 98            1  1.657436050  0  0.44482820  0.00000000
    #> 99            1  2.378333477  0 -0.44507681  0.00000000
    #> 100           1  2.959965426  1  0.03676946  0.03676946
    #> attr(,"assign")
    #> [1] 0 1 2 3 4
    

    Created on 2024-09-09 with reprex v2.1.0

    You could also evaluate the call, e.g. eval(c[[2]]) will give you the same output as as.formula(c[[2]]). Does that help with your use-case?