cell_support_xyz <- function(level, zero)
{
for(i in 1:level[1]){
for(j in 1:level[2]){
for(k in 1:level[3]){
cat("cell (", i, ", ", j, ", ", k,") --> support set = (",
+!(i == zero[1]), ", ", +!(j == zero[2]), ", ", +!(k == zero[3]), ")\n", sep = "")
}
}
}
}
#Example 1
l<-c(2,3,2)
z<-c(1,1,1)
> cell_support_xyz(l,z)
cell (1, 1, 1) --> support set = (0, 0, 0)
cell (1, 1, 2) --> support set = (0, 0, 1)
cell (1, 2, 1) --> support set = (0, 1, 0)
cell (1, 2, 2) --> support set = (0, 1, 1)
cell (1, 3, 1) --> support set = (0, 1, 0)
cell (1, 3, 2) --> support set = (0, 1, 1)
cell (2, 1, 1) --> support set = (1, 0, 0)
cell (2, 1, 2) --> support set = (1, 0, 1)
cell (2, 2, 1) --> support set = (1, 1, 0)
cell (2, 2, 2) --> support set = (1, 1, 1)
cell (2, 3, 1) --> support set = (1, 1, 0)
cell (2, 3, 2) --> support set = (1, 1, 1)
The above code works just fine. But I want to avoid for loop. Here I used 3 for loops (because the length of both argument vectors is 3). If the length of vectors increases or decreases the function won't work (I need to adjust for loops accordingly); which is why I want to replace for-loop with some efficient alternative that works for any length. Any suggestion?
One way to remove the for loop and making the solution flexible enough for any length input.
We use expand.grid to create all possible combinations of level and use apply rowwise to create a string to print.
cell_support_xyz <- function(level, zero) {
tmp <- do.call(expand.grid, lapply(level, seq))
abc <- apply(tmp, 1, function(x)
cat(sprintf('cell (%s) --> support set = (%s)\n',
toString(x), toString(+(x != zero)))))
}
l<-c(2,3,2)
z<-c(1,1,1)
cell_support_xyz(l, z)
#cell (1, 1, 1) --> support set = (0, 0, 0)
#cell (2, 1, 1) --> support set = (1, 0, 0)
#cell (1, 2, 1) --> support set = (0, 1, 0)
#cell (2, 2, 1) --> support set = (1, 1, 0)
#cell (1, 3, 1) --> support set = (0, 1, 0)
#cell (2, 3, 1) --> support set = (1, 1, 0)
#cell (1, 1, 2) --> support set = (0, 0, 1)
#cell (2, 1, 2) --> support set = (1, 0, 1)
#cell (1, 2, 2) --> support set = (0, 1, 1)
#cell (2, 2, 2) --> support set = (1, 1, 1)
#cell (1, 3, 2) --> support set = (0, 1, 1)
#cell (2, 3, 2) --> support set = (1, 1, 1)
You can do that in 2 steps:
l<-c(2,3,2)
z<-c(1,1,1)
cells <- expand.grid(lapply(l, seq))
t(apply(cells, 1, function(x) 1L*!(x == z)))
cells contains all the combinations. If the order matters, you can simply reorder it:
cells <- dplyr::arrange(cells, Var1, Var2, Var3)
Then, for each row (apply(,1,)) you can use == which is already vectorized to compare the entire row to the entire z vector.
Multiplying by 1L makes it integer, same as +.
Related
I am writing a function for minimization using optim. The task is to solve some similar optimization tasks in loop.
# K and k are always the same (they are read from a file)
K <- matrix(data = c(1, 2, 1, 2, 1,
2, 16, 2, 1, 2,
1, 2, 8, 2, 1,
2, 1, 2, 16, 2,
1, 2, 1, 2, 32),
nrow = 5, ncol = 5, byrow = TRUE)
k <- c(-2, 4, 12, 0, 2)
# j will be changed
minimize <- function(beta){ #function to minimize (for beta)
value <- (1/2)*(t(beta)%*%K%*%beta) - t(k)%*%beta + j*abs(sum(beta)-n_s)
return(value)
}
myfunc <- function(K, k, m) #K is matrix, k is vector
{
j_values <- 10^seq(-5, 5, length = m)
for (i in 1:m)
{
current_j_value <- j_values[i]
#I want to set j in minimize function as current_j_value (and also my k and K from file)
# and then minimize it
myans <- optim(c(0, 0, 0, 0, 0), minimize) # using minimize(K, k, j) doesn't work
print(myans$par)
}
}
myfunc(K, k, 5)
My question is how to give arguments to my minimize function (to create it dynamically?) and then use it in optim.
If youw ant to include extra parameters in you minimize function you can add these in the optim call as from the documentation see ?optim the dots (...)
... Further arguments to be passed to fn and gr.
So including j, k, K and n_s in minimize
minimize <- function(beta, j, k, K, n_s){ #function to minimize (for beta)
value <- (1/2)*(t(beta)%*%K%*%beta) - t(k)%*%beta + j*abs(sum(beta)-n_s)
return(value)
}
and then adding these to the optim call (I have set n_s = 0) like,
myfunc <- function(K, k, m) #K is matrix, k is vector
{
j_values <- 10^seq(-5, 5, length = m)
for (i in 1:m)
{
current_j_value <- j_values[i]
#I want to set j in minimize function as current_j_value (and also my k and K from file)
# and then minimize it
myans <- optim(c(0, 0, 0, 0, 0), minimize, j = current_j_value, k = k, K = K, n_s = 0) # using minimize(K, k, j) doesn't work
print(myans$par)
}
}
Running this then,
> myfunc(K, k, 5)
[1] -6.7956860 0.7999990 1.9999999 0.5333326 0.1290324
[1] -6.7911329 0.7996483 2.0000002 0.5329818 0.1290322
[1] -5.3512894 0.6889257 1.9999436 0.4222287 0.1290095
[1] -2.80295781 0.61426579 1.95348934 0.24715200 -0.01194974
[1] -1.2999142 0.4313710 1.3088572 -0.5764644 0.1361504
All the code together
# K and k are always the same (they are read from a file)
K <- matrix(data = c(1, 2, 1, 2, 1,
2, 16, 2, 1, 2,
1, 2, 8, 2, 1,
2, 1, 2, 16, 2,
1, 2, 1, 2, 32),
nrow = 5, ncol = 5, byrow = TRUE)
k <- c(-2, 4, 12, 0, 2)
# j will be changed
minimize <- function(beta, j, k, K, n_s){ #function to minimize (for beta)
value <- (1/2)*(t(beta)%*%K%*%beta) - t(k)%*%beta + j*abs(sum(beta)-n_s)
return(value)
}
myfunc <- function(K, k, m) #K is matrix, k is vector
{
j_values <- 10^seq(-5, 5, length = m)
for (i in 1:m)
{
current_j_value <- j_values[i]
#I want to set j in minimize function as current_j_value (and also my k and K from file)
# and then minimize it
myans <- optim(c(0, 0, 0, 0, 0), minimize, j = current_j_value, k = k, K = K, n_s = 0) # using minimize(K, k, j) doesn't work
print(myans$par)
}
}
myfunc(K, k, 5)
I'm looking for an efficient way to plot time, x, y, z with different colors for different objects - to view proximity of the objects over time.
plot3D::line3D works with add = TRUE, but it is not very elegant. Here's a sample code that works:
data$object_id <- factor(data$object_id)
library(plot3D)
for(tr in unique(data$object_id)) {
lines3D(data$x[data$object_id == tr], data$y[data$object_id == tr], data$z[data$ba object_id ll == tr], add = T, col = data$object_id[data$object_id == tr])
}
Example data:
data <- data.frame(object_id = c(1, 1, 2, 2), t = c(0, 1, 0, 1), x = c(0, 1, 1, 0), y = c(0, 1, 1, 0), altitude = c(0, 1, 1, 0))
Desired result: path traced by different objects at a given time along with an arrow that indicates the current direction of heading (determined by joining the last 2 known positions).
At time t = 0, this should yield nothing or should yield points. At t = 1, this should yield 2 lines (one over the other) of different colors: one color for each object.
2D equivalent is ggplot2::geom_path, which does all the heavy-lifting using group parameter which joins all the paths by the grouping variable.
I have a very large dataframe that looks like so:
month <- c(201101, 201101, 201101, 201102, 201102, 201102, 201103, 201103, 201103, 201104, 201104, 201104)
su <- as.factor(c(045110B238, 045110B238, 045110B238, 045110B238, 045110B238,045110B238, 045110B238, 045110B238, 045110B238, 045110B238, 045110B238, 045110B238))
item <- as.factor(c(045110B238A01, 045110B238A02, 045110B238A03, 045110B238A01, 045110B238A02, 045110B238A03, 045110B238A01, 045110B238A02, 045110B238A03, 045110B238A01, 045110B238A02, 045110B238A03))
item.dlq <- c(1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1)
df <- data.frame(month, su, item, item.dlq)
Using the item.dlq variable I count the cumulative number of months for which each itemcode has item.dlq == 1:
library(dplyr)
df <- data.frame(df %>%
group_by(itemcode, grp = cumsum(item.dlq == 0)) %>%
mutate(item.cum.dlq = cumsum(item.dlq)))
which should give me a vector like so:
item.cum.dlq <- c(1, 1, 1, 2, 0, 2, 3, 1, 3, 4, 2, 4)
Based on the information above, I would like to
create a variable that counts the number of consecutive months in which ALL items for the su have values of dlq==1.
count the number of consecutive months when at least 1 itemcode has a value of 1. For example, where month is equal to 201102 (i.e. 2/2011), item 045110B238A02 has item.dlq == 0, so only 2/3 items have dlq == 1.
Note that there is only one value of su in the example above, but there are many in the full data frame I am working with. I would also like to compress the data frame as well, if possible, to avoid carrying around unnecesary observations. Here is what the raw data would look like without compressing:
su.cum.fulldlq <- c(1, 1, 1, 0, 0, 0, 1, 1, 1, 2, 2, 2) ## all items dlq ==1
su.cum.partdlq <- c(0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0) ## at least 1 item but not all have dlq == 1
If the data frame were compressed, it would look like so:
month <- c(201101, 201102, 201103, 201104)
su <- c(045110B238, 045110B238, 045110B238, 045110B238)
su.cum.fulldlq <- c(1, 0, 1, 2)
su.cum.partdlq <- c(0, 1, 0, 0)
I was thinking something along the lines of this, but I keep getting error messages.
df <- data.frame(df %>%
group_by(su, month)) %>%
mutate(burden = n_distinct(itemcode)) # count number of items
mutate(dlq.items = n_distinct(dlq == 1)) %>% # count number of items where dlq == 1
mutate(full.dlq = ifelse(burden == dlq_items, 1, 0)) %>% # if number of items equals the number of items with dlq == 1, then full.dlq == 1.
after this i am not certain at all.
Is there a way to do so using dplyr? If not, any other approaches would be welcome. If something is not clear please comment and I will change it. Either way, any help or suggestions would be greatly appreciated. Thanks so much!
Let d1 and d2 be matrices over the integers Z. How can I compute the group quotient ker d1 / im d2 in Sage?
So far I've been able to compute a basis for the kernel and image as follows:
M24 = MatrixSpace(IntegerRing(),2,4)
d1 = M24([-1,1, 1,-1, -1,1, 1,-1])
kerd1 = d1.right_kernel().basis()
M43 = MatrixSpace(IntegerRing(),4,3)
d2 = M43([1,1,-1, 1,-1,-1, 1,-1,1, 1,1,1])
imd2 = d2.column_space().basis()
which gives output:
kerd1 = [
(1, 0, 0, -1),
(0, 1, 0, 1),
(0, 0, 1, 1)
]
imd2 = [
(1, 1, 1, 1),
(0, 2, 0, -2),
(0, 0, 2, 2)
]
I tried to compute the quotient like this:
Z4.<a,b,c,d> = AbelianGroup(4, [0,0,0,0])
G = Z4.subgroup([a/d, b*d, c*d])
H = Z4.subgroup([a*b*c*d, b^2/d^2, c^2*d^2])
G.quotient(H)
But I got a NotImplementedError.
I found two ways to do this:
d1 = matrix(ZZ,4,2, [-1,1, 1,-1, -1,1, 1,-1]).transpose()
d2 = matrix(ZZ,4,3, [1,1,-1, 1,-1,-1, 1,-1,1, 1,1,1])
(d1.right_kernel() / (d2.column_space())).invariants()
# OUTPUT: (2, 2)
ChainComplex([d2, d1]).homology()[1]
# OUTPUT: C2 x C2
Imagine a diamond-shaped isometric map, which is basically a 2D array with (x,y) coordinates and the top cell as the origin, as marked in the cells:
I want to iterate through these cells from back to front, in the following order:
What's the algorithm to loop in this way through an unknown same-sided map?
Expected output: [0,0], [0,1], [1,0], [0,2], [1,1], [2,0], [0,3], etc
python pseudocode:
def iterate_cells(n):
for i in range(n):
for j in range(i+1):
yield (j, i-j)
for i in range(1, n+1):
for j in range(n - i):
yield(i+j, n-j-1)
output:
In [119]: list(iterate_cells(5))
Out[119]:
[(0, 0),
(0, 1),
(1, 0),
(0, 2),
(1, 1),
(2, 0),
(0, 3),
(1, 2),
(2, 1),
(3, 0),
(0, 4),
(1, 3),
(2, 2),
(3, 1),
(4, 0),
(1, 4),
(2, 3),
(3, 2),
(4, 1),
(2, 4),
(3, 3),
(4, 2),
(3, 4),
(4, 3),
(4, 4)]
Considering map is contained in a matrix M(n,n):
// lateral loop above diagonal
for (int i=0; i<n; i++) {
// diagonal loop
for (int j=0; j<i; j++) {
// the coords you are looking for are: row=(i-j), col=(i+j)
int currentTileValue = M[i-j, i+j];
}
}
// sub-diagonal lateral loop
for (int j=1; j<n; j++) {
// diagonal loop
for (int i=0; i<(n-j); i++) {
// the coords you are looking for are: row=(j-i), col=(j+i)
int currentTileValue = M[j-i, j+i];
}
}
didn't test it in detail, but I think i think it works. Anyhow you get the idea.