1

I need to assign fixed numbers, let's say "x", "y", "z", etc., randomly to a matrix. How can I do that? I did search about it but they all explained how to make a matrix with random numbers. But my numbers aren't random. I know what numbers I want in my matrix, I don't know how to assign them randomly to my matrix. And I can't write any line of codes for that to put it here to correct it.

Here is an example. Assume that I have numbers 1 and 1.2. I want to generate a 20*10 matrix with its elements randomly chosen from 1 and 1.2 . An example matrix looks like this:

1    1     1.2  1
1.2  1     1.2  1.2
1    1.2   1    1.2
1    1.2   1    1

Each number should occur in each row at least once.

Thanks a lot

Fate
  • 43
  • 6
  • 3
    `matrix(sample(c(1, 1.2), 20*10, replace=TRUE), ncol=10)` ? – Cath Dec 21 '17 at 11:48
  • It works. Thanks a lot. I need each number to occur in each row at least once. Does the code do that? – Fate Dec 21 '17 at 11:52
  • @Fate To ensure each number occurs in each row at least once, you'd need something more like `t(replicate(20, sample(c(1, 1.2), 10, replace = TRUE)))` – duckmayr Dec 21 '17 at 12:00
  • 2
    @duckmayr please revise your answer. Your statement is not true. For example `set.seed(7)` gives that row 14 contains only `1.2`. – nadizan Dec 21 '17 at 12:10
  • @nadizan Fair enough; will do shortly – duckmayr Dec 21 '17 at 12:12

1 Answers1

4

Solution

t(replicate(20, sample(c(1, 1.2, sample(c(1, 1.2), 8, replace = TRUE)))))

Explanation

sample(c(1, 1.2, sample(c(1, 1.2), 8, replace = TRUE)))

creates a randomly ordered sample of 10 that ensures one of the elements will be 1, one of the elements will be 1.2, and the other 8 will be randomly selected from 1 and 1.2.

t(replicate(20, sample(c(1, 1.2, sample(c(1, 1.2), 8, replace = TRUE)))))

does this 20 times and transposes the answer to be of the dimensions you'd like.

UPDATE

After additional comments, it seems you need to be able to accomplish two different things:

  1. Create an n by m matrix randomly filled with the values of x subject to the constraint that each row of the resulting matrix contains every element of x at least once.
  2. Create an n by m matrix randomly filled with the values of x subject to the constraint that each row of the resulting matrix has more than one unique value.

So, at this point, I would recommend creating functions:

f1 <- function(x, n, m) {
    N <- length(x)
    if ( N > m ) {
        stop('x is longer than the number of columns requested.', call. = FALSE)
    }
    return(t(replicate(n, sample(c(x, sample(x, m - N, replace = TRUE))))))
}

f2 <- function(x, n, m) {
    if ( length(unique(x)) == 1 ) {
        stop('x has only one unique element.', call. = FALSE)
    }
    result <- t(replicate(n, sample(x, m, replace = TRUE)))
    while ( any(apply(result, 1, function(x) length(unique(result)) == 1)) ) {
        result <- t(replicate(n, sample(x, m, replace = TRUE)))
    }
    return(result)
}

(If I were you I'd also give those functions more informative names).

f1() accomplishes what my original answer does (corresponding to number 1. above) for arbitrary x, n, and m. f2() accomplishes the new request (corresponding to number 2. above); however, note there are probably better ways to accomplish this task, and this approach (a while loop) could take an arbitrary amount of time depending on the values of x, n, m, and chance. Here are example calls of the functions:

set.seed(1234)
x <- c(1, 1.2)
f1(x, 20, 10)

      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]  1.2  1.2  1.2  1.2  1.2  1.0  1.2  1.0  1.0   1.0
 [2,]  1.0  1.0  1.0  1.0  1.0  1.2  1.0  1.0  1.0   1.2
 [3,]  1.0  1.2  1.2  1.2  1.2  1.2  1.0  1.0  1.2   1.0
 [4,]  1.2  1.0  1.2  1.0  1.2  1.0  1.2  1.2  1.0   1.0
 [5,]  1.2  1.0  1.2  1.2  1.0  1.0  1.2  1.0  1.0   1.0
 [6,]  1.2  1.0  1.0  1.0  1.2  1.0  1.2  1.0  1.0   1.0
 [7,]  1.2  1.0  1.0  1.0  1.2  1.2  1.0  1.0  1.0   1.2
 [8,]  1.0  1.0  1.2  1.0  1.2  1.2  1.0  1.0  1.0   1.2
 [9,]  1.0  1.2  1.2  1.2  1.2  1.2  1.0  1.2  1.0   1.0
[10,]  1.0  1.2  1.2  1.0  1.0  1.0  1.2  1.0  1.0   1.0
[11,]  1.0  1.2  1.0  1.2  1.0  1.2  1.2  1.0  1.2   1.0
[12,]  1.2  1.2  1.2  1.0  1.2  1.2  1.0  1.2  1.2   1.2
[13,]  1.2  1.0  1.0  1.2  1.2  1.0  1.2  1.0  1.0   1.0
[14,]  1.2  1.0  1.2  1.0  1.2  1.0  1.0  1.0  1.2   1.0
[15,]  1.2  1.0  1.0  1.2  1.2  1.2  1.0  1.0  1.0   1.0
[16,]  1.0  1.2  1.2  1.2  1.2  1.0  1.2  1.0  1.0   1.2
[17,]  1.2  1.2  1.0  1.2  1.2  1.2  1.0  1.2  1.2   1.0
[18,]  1.2  1.0  1.0  1.0  1.2  1.2  1.0  1.2  1.2   1.2
[19,]  1.2  1.2  1.0  1.0  1.2  1.0  1.2  1.2  1.0   1.0
[20,]  1.2  1.0  1.2  1.0  1.0  1.2  1.0  1.2  1.0   1.2

x <- c(1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.4, 2.6, 2.8, 3)
f2(x, 20, 10)

      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]  1.0  2.2  2.0  1.6  2.8  3.0  2.4  1.4  2.8   2.4
 [2,]  3.0  1.4  2.8  2.0  1.6  1.8  2.6  1.2  1.8   2.4
 [3,]  1.6  1.4  1.0  1.2  1.4  1.2  2.4  1.4  3.0   3.0
 [4,]  2.4  2.6  2.6  2.4  1.2  3.0  2.2  2.0  1.0   1.8
 [5,]  2.4  1.8  2.6  2.6  2.2  1.4  2.6  1.2  2.2   1.8
 [6,]  2.6  2.6  3.0  1.4  2.8  1.8  2.0  2.6  1.2   1.8
 [7,]  2.4  2.8  1.6  1.2  3.0  1.4  1.0  1.8  1.6   1.6
 [8,]  2.4  2.6  1.8  3.0  1.4  2.4  1.8  3.0  2.6   2.2
 [9,]  2.6  2.8  2.6  2.0  3.0  2.2  2.8  2.2  2.2   1.0
[10,]  1.4  2.6  3.0  3.0  2.6  2.4  1.4  2.2  2.2   1.0
[11,]  1.8  2.8  1.8  2.0  1.2  1.4  2.2  1.8  2.2   2.2
[12,]  1.2  1.6  1.0  3.0  1.8  3.0  2.0  2.0  2.4   1.2
[13,]  2.0  2.2  2.4  1.8  1.2  1.0  2.6  2.4  2.6   1.2
[14,]  2.2  2.6  3.0  1.6  2.4  1.6  2.2  1.0  2.2   2.2
[15,]  2.4  2.6  2.8  1.0  2.4  2.8  2.6  2.8  1.2   2.6
[16,]  1.6  3.0  3.0  2.2  1.2  2.6  2.2  1.0  2.4   1.6
[17,]  2.8  1.4  1.6  3.0  2.2  2.6  1.0  1.0  2.2   1.4
[18,]  1.4  2.2  1.8  2.6  1.2  3.0  2.4  2.4  2.6   2.0
[19,]  1.8  2.2  3.0  1.4  2.6  1.8  2.8  2.8  3.0   3.0
[20,]  1.4  1.4  2.6  1.2  2.8  3.0  2.0  1.0  2.2   2.8
duckmayr
  • 16,303
  • 3
  • 35
  • 53
  • Thanks a lot for your comprehensive explanation. It works. But can it be used when I have a set of 15 numbers and I want to make a random 20*10 matrix with each row to have at least one different element? I mean that I wanna make a matrix with no row with all the same element. I want my rows to have at least one different element. – Fate Dec 21 '17 at 13:08
  • Will that work? t(replicate(20, sample(c(1, sample(c(1, 1.2,1.4,1.6,1.8,2,2.2,2.4,2.6,2.8,3,3.2,3.4,3.6,3.8), 9, replace = TRUE))))) . but no. here I tell R to have 1 in each row at least once. That's not I want. – Fate Dec 21 '17 at 13:15
  • @Fate I have updated my answer to consider also this new twist on the problem. – duckmayr Dec 21 '17 at 13:40
  • Thank you very much. Yeah I had two different questions: 1- How to make a matrix where each number occures at least once in each row 2- How to make a matrix where each row has more than one value. In question number 2, I don't want each number to occur at least once in each row. Your functions work well. Thanks a lot. You're so knowledgeable. Would you please recommend me some books where I can learn R programming? Thanks a lot – Fate Dec 21 '17 at 13:56
  • And what is set.seed(1234) please? – Fate Dec 21 '17 at 14:06
  • 1
    @Fate When using (pseudo-)random number generation, setting the seed used by the random number generator ensures others will get the exact same result when running your code despite having steps in the code that are random. Good sources to read up on this are [this SO question](https://stackoverflow.com/questions/13605271/reasons-for-using-the-set-seed-function), the [Wikipedia for pseudo-random number generation](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) and, of course, running `help("set.seed")` in R – duckmayr Dec 21 '17 at 14:13
  • Thank you very much. I appreciate that. – Fate Dec 21 '17 at 14:15