|
1 | 1 | # File src/library/base/R/interaction.R |
2 | 2 | # Part of the R package, https://www.R-project.org |
3 | 3 | # |
4 | | -# Copyright (C) 1995-2013 The R Core Team |
| 4 | +# Copyright (C) 1995-2025 The R Core Team |
5 | 5 | # |
6 | 6 | # This program is free software; you can redistribute it and/or modify |
7 | 7 | # it under the terms of the GNU General Public License as published by |
@@ -29,39 +29,50 @@ interaction <- function(..., drop = FALSE, sep = ".", lex.order = FALSE) |
29 | 29 | narg <- length(args) |
30 | 30 | } |
31 | 31 | for(i in narg:1L) { |
32 | | - f <- as.factor(args[[i]])[, drop = drop] |
33 | | - l <- levels(f) |
34 | | - if1 <- as.integer(f) - 1L |
| 32 | + x <- as.factor(args[[i]])[, drop = drop] |
| 33 | + ax <- as.integer(x) - 1L |
| 34 | + lx <- levels(x) |
35 | 35 | if(i == narg) { |
36 | | - ans <- if1 |
37 | | - lvs <- l |
| 36 | + ay <- ax |
| 37 | + ly <- lx |
38 | 38 | } else { |
| 39 | + nx <- length(lx) |
| 40 | + ny <- length(ly) |
39 | 41 | if(lex.order) { |
40 | | - ll <- length(lvs) |
41 | | - ans <- ans + ll * if1 |
42 | | - lvs <- paste(rep(l, each = ll), rep(lvs, length(l)), sep=sep) |
| 42 | + ay <- ay + ny * ax |
| 43 | + if(drop) { |
| 44 | + az <- sort(unique(ay)) |
| 45 | + ly <- paste(lx[az %/% ny + 1L], ly[az %% ny + 1L], |
| 46 | + sep = sep) |
| 47 | + ay <- match(ay, az) - 1L |
| 48 | + } else { |
| 49 | + ly <- paste(rep(lx, each = ny), rep(ly, nx), |
| 50 | + sep = sep) |
| 51 | + } |
43 | 52 | } else { |
44 | | - ans <- ans * length(l) + if1 |
45 | | - lvs <- paste(rep(l, length(lvs)), |
46 | | - rep(lvs, each = length(l)), sep=sep) |
| 53 | + ay <- ay * nx + ax |
| 54 | + if(drop) { |
| 55 | + az <- sort(unique(ay)) |
| 56 | + ly <- paste(lx[az %% nx + 1L], ly[az %/% nx + 1L], |
| 57 | + sep = sep) |
| 58 | + ay <- match(ay, az) - 1L |
| 59 | + } else { |
| 60 | + ly <- paste(rep(lx, ny), rep(ly, each = nx), |
| 61 | + sep = sep) |
| 62 | + } |
47 | 63 | } |
48 | | - while(j <- anyDuplicated(lvs)) { |
| 64 | + while(j <- anyDuplicated(ly)) { |
49 | 65 | ## If levels at positions i and j > i are the same, we |
50 | 66 | ## need to drop the one at j, change the code for that |
51 | 67 | ## level to the code for level i, and decrease all codes |
52 | 68 | ## beyond the code for level j by one. |
53 | | - i <- match(lvs[j], lvs) |
54 | | - lvs <- lvs[-j] |
| 69 | + i <- match(ly[j], ly) |
| 70 | + ly <- ly[-j] |
55 | 71 | j <- j - 1L |
56 | | - ans[ans == j] <- i - 1L |
57 | | - ans[ans > j] <- ans[ans > j] - 1L |
58 | | - } |
59 | | - if(drop) { |
60 | | - olvs <- lvs |
61 | | - lvs <- lvs[sort(unique(ans+1L))] |
62 | | - ans <- match(olvs[ans+1L], lvs) - 1L |
| 72 | + ay[ay == j] <- i - 1L |
| 73 | + ay[ay > j] <- ay[ay > j] - 1L |
63 | 74 | } |
64 | 75 | } |
65 | 76 | } |
66 | | - structure(as.integer(ans+1L), levels=lvs, class = "factor") |
| 77 | + structure(as.integer(ay + 1L), levels = ly, class = "factor") |
67 | 78 | } |
0 commit comments