What ways exist to create an array with given dimensions from a given sequence in Julia? - julia

I'm new to Julia and I could not find any useful information on the following: I would like to create an array of given dimensions and fill it with a given sequence.
m,n = 10,10 # dimensions
i = 1:100 # sequence
I've tried to use collect, but this gives me a single column array. I have also tried it the Julia way
[? for i in 1:m, j in 1:n]
but I don't know what I could insert for ?.

The easiest way is reshape(i, m,n) (potentially together with a collect if you really need an Array{Int64,2}):
julia> reshape(i,m,n)
10×10 reshape(::UnitRange{Int64}, 10, 10) with eltype Int64:
1 11 21 31 41 51 61 71 81 91
2 12 22 32 42 52 62 72 82 92
3 13 23 33 43 53 63 73 83 93
4 14 24 34 44 54 64 74 84 94
5 15 25 35 45 55 65 75 85 95
6 16 26 36 46 56 66 76 86 96
7 17 27 37 47 57 67 77 87 97
8 18 28 38 48 58 68 78 88 98
9 19 29 39 49 59 69 79 89 99
10 20 30 40 50 60 70 80 90 100
julia> collect(ans)
10×10 Array{Int64,2}:
1 11 21 31 41 51 61 71 81 91
2 12 22 32 42 52 62 72 82 92
3 13 23 33 43 53 63 73 83 93
4 14 24 34 44 54 64 74 84 94
5 15 25 35 45 55 65 75 85 95
6 16 26 36 46 56 66 76 86 96
7 17 27 37 47 57 67 77 87 97
8 18 28 38 48 58 68 78 88 98
9 19 29 39 49 59 69 79 89 99
10 20 30 40 50 60 70 80 90 100
To answer your question what to put as ? in the array comprehension approach, you must convert the cartesian index to a linear index, for example like so:
julia> [i[LinearIndices((m,n))[p,q]] for p in 1:m, q in 1:n]
10×10 Array{Int64,2}:
1 11 21 31 41 51 61 71 81 91
2 12 22 32 42 52 62 72 82 92
3 13 23 33 43 53 63 73 83 93
4 14 24 34 44 54 64 74 84 94
5 15 25 35 45 55 65 75 85 95
6 16 26 36 46 56 66 76 86 96
7 17 27 37 47 57 67 77 87 97
8 18 28 38 48 58 68 78 88 98
9 19 29 39 49 59 69 79 89 99
10 20 30 40 50 60 70 80 90 100
Of course, you can also calculate the linear index yourself, [i[(q-1)*m + p] for p in 1:m, q in 1:n].
Alternatively, you can preallocate the array and fill it in a linear fashion:
julia> result = Matrix{Int64}(undef, m,n);
julia> result[:] .= i;
julia> result
10×10 Array{Int64,2}:
1 11 21 31 41 51 61 71 81 91
2 12 22 32 42 52 62 72 82 92
3 13 23 33 43 53 63 73 83 93
4 14 24 34 44 54 64 74 84 94
5 15 25 35 45 55 65 75 85 95
6 16 26 36 46 56 66 76 86 96
7 17 27 37 47 57 67 77 87 97
8 18 28 38 48 58 68 78 88 98
9 19 29 39 49 59 69 79 89 99
10 20 30 40 50 60 70 80 90 100
which is basically equivalent to the naive, explicit solution
julia> result = Matrix{Int64}(undef, m,n);
julia> for k in eachindex(i) result[k] = i[k] end
julia> result
10×10 Array{Int64,2}:
1 11 21 31 41 51 61 71 81 91
2 12 22 32 42 52 62 72 82 92
3 13 23 33 43 53 63 73 83 93
4 14 24 34 44 54 64 74 84 94
5 15 25 35 45 55 65 75 85 95
6 16 26 36 46 56 66 76 86 96
7 17 27 37 47 57 67 77 87 97
8 18 28 38 48 58 68 78 88 98
9 19 29 39 49 59 69 79 89 99
10 20 30 40 50 60 70 80 90 100

Related

Extracting first n elements from a list of vectors to a new list

I have a list with multiple vectors such as
List1<- list(v1=sample(1:100,150,replace=TRUE),v2=sample(1:100,150,replace=TRUE),v3=sample(1:100,150,replace=TRUE),v4=sample(1:100,150,replace=TRUE))
The output is something like
$v1
[1] 37 20 26 46 70 70 46 58 99 45 33 51 54 71 1 46 70 39 97 50 68 15 3 78 99 85 26
[28] 41 49 64 1 49 91 52 23 67 53 96 79 64 7 21 10 56 42 36 4 32 27 23 8 3 74 58
[55] 58 78 51 59 24 88 69 31 58 95 19 27 65 34 16 66 56 7 68 85 43 44 34 18 34 25 54
[82] 84 69 9 35 53 19 100 28 31 66 64 24 73 39 28 70 47 57 17 67 27 54 79 15 19 23 60
[109] 60 84 65 98 47 57 10 38 65 48 31 23 12 94 81 16 100 45 71 61 24 6 33 100 22 84 74
[136] 92 43 49 41 59 57 40 22 35 78 46 83 27 65 20
$v2
[1] 97 45 47 23 32 88 45 93 88 64 100 21 85 70 99 70 59 54 20 45 62 63 91 42 24 74 20
[28] 29 3 67 96 31 1 11 50 24 32 14 27 41 73 89 92 55 45 83 77 34 94 51 80 93 52 2
[55] 73 51 63 56 78 58 48 91 38 97 28 53 94 60 45 24 2 74 17 38 40 49 61 81 59 29 80
[82] 60 47 9 71 37 9 10 68 98 6 34 52 24 36 41 28 37 46 75 63 10 30 69 23 100 29 83
[109] 88 60 87 53 51 94 31 48 17 71 14 23 12 71 21 47 79 23 96 42 95 2 16 81 72 64 15
[136] 28 40 40 77 13 99 87 29 95 64 18 46 49 25 74
$v3
[1] 67 22 45 78 79 92 24 25 22 95 67 91 4 72 37 49 87 32 80 2 54 96 48 79 39 47 75
[28] 3 24 37 93 64 97 83 50 85 61 93 78 53 35 77 14 12 70 74 24 54 26 73 33 28 19 35
[55] 87 26 62 85 29 62 21 65 27 64 8 67 76 86 74 80 68 66 34 97 83 11 30 69 20 79 90
[82] 36 18 7 58 9 32 88 64 22 76 99 71 62 10 62 50 70 79 37 73 100 4 47 17 96 79 29
[109] 55 58 79 46 45 81 57 74 21 69 86 60 21 3 79 87 8 88 79 65 82 72 36 97 1 73 82
[136] 29 97 81 88 42 35 10 98 66 17 76 85 84 31 51
$v4
[1] 66 15 87 78 6 2 57 57 21 46 97 83 70 56 2 92 2 57 89 69 58 9 24 89 65 48 92
[28] 87 91 100 91 99 21 16 26 83 38 90 57 14 5 74 72 33 52 59 92 85 8 80 53 82 41 91
[55] 69 33 8 14 10 25 88 35 21 48 60 81 57 13 16 69 50 30 16 1 89 73 17 3 46 86 71
[82] 75 16 91 73 25 92 93 54 59 59 27 25 51 9 27 18 74 66 5 51 60 63 17 94 25 22 100
[109] 4 95 57 89 56 26 36 52 40 74 31 46 16 18 9 27 51 87 74 50 28 87 85 52 34 76 31
[136] 56 84 25 91 33 98 80 2 30 49 90 23 21 2 26
I want to extract the first 6 elements of each of the vectors, and save it to a new list, such that the output may look like
$v1
[1] 37 20 26 46 70 70
$v2
[1] 97 45 47 23 32 88
$v3
[1] 67 22 45 78 79 92
$v4
[1] 66 15 87 78 6 2
I have tried sapply(List1,head,6), but this is not the output I was looking for.

How to access very first object in differently deep nested lists?

I need to access the first element of a list. The problem is that the lists vary in the way how deep they are nested. Here is an example:
list1 <- list(ts(1:100),
list(1:19,
factor(letters)))
list2 <- list(list(list(ts(1:100), data.frame(a= rnorm(100))),
matrix(rnorm(10))),
NA)
My expected output is to get the time seriests(1:100) for both lists, i.e. list1[[1]] and list2[[1]][[1]][[1]]. I've tried different stuff, among others lapply(list2, `[[`, 1) which here does not work here.
Another base R solution - you could do this with a recursive function:
list1 <- list(ts(1:100),
list(1:19,
factor(letters)))
list2 <- list(list(list(ts(1:100), data.frame(a= rnorm(100))),
matrix(rnorm(10))),
NA)
recursive_fun <- function(my_list) {
if (inherits(my_list, 'list')) {
Recall(my_list[[1]])
} else {
my_list
}
}
Output:
> recursive_fun(list1)
Time Series:
Start = 1
End = 100
Frequency = 1
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
[31] 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
[61] 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
[91] 91 92 93 94 95 96 97 98 99 100
> recursive_fun(list2)
Time Series:
Start = 1
End = 100
Frequency = 1
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
[31] 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
[61] 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
[91] 91 92 93 94 95 96 97 98 99 100
You can use rrapply::rrapply:
library(rrapply)
firstList1 <- rrapply(list1, how = "flatten")[[1]]
firstList2 <- rrapply(list2, how = "flatten")[[1]]
all.equal(firstList1, firstList2)
# [1] TRUE
output
> rrapply(list1, how = "flatten")[[1]]
Time Series:
Start = 1
End = 100
Frequency = 1
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
[27] 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
[53] 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
[79] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Using a while loop :
x <- list1
while (inherits(x <- x[[1]], "list")) {}
x
#> Time Series:
#> Start = 1
#> End = 100
#> Frequency = 1
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#> [19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#> [37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#> [55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#> [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#> [91] 91 92 93 94 95 96 97 98 99 100
x <- list2
while (inherits(x <- x[[1]], "list")) {}
x
#> Time Series:
#> Start = 1
#> End = 100
#> Frequency = 1
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#> [19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#> [37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#> [55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#> [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#> [91] 91 92 93 94 95 96 97 98 99 100
We can combine while loop with purrr::pluck. This avoids an actual recursive function, which could be a problem with deeply nested lists.
library(purrr)
get_list <- function(x){
while(is.list(x)){
x <- pluck(x, 1)
}
x
}
We can also set the function to be called 'recursively' until it finds a "ts" class object:
get_list <- function(x){
while(!is(x, 'ts')){
x <- pluck(x, 1)
}
x
}
output
get_list(list2)
Time Series:
Start = 1
End = 100
Frequency = 1
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
[46] 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
[91] 91 92 93 94 95 96 97 98 99 100
Another possible solution, using purrr::pluck and purrr::vec_depth:
library(tidyverse)
pluck(list1, !!!(rep(1, vec_depth(list1)-2) %>% as.list()))
#> Time Series:
#> Start = 1
#> End = 100
#> Frequency = 1
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#> [19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#> [37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#> [55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#> [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#> [91] 91 92 93 94 95 96 97 98 99 100
pluck(list2, !!!(rep(1, vec_depth(list2)-2) %>% as.list()))
#> Time Series:
#> Start = 1
#> End = 100
#> Frequency = 1
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#> [19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#> [37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#> [55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#> [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#> [91] 91 92 93 94 95 96 97 98 99 100
base R solution I've just got the idea for a pretty simple function. It is a while loop that runs until the element is not a list.
myfun <- function(mylist){
dig_deeper <- TRUE
while(dig_deeper){
mylist<- my_list[[1]]
dig_deeper <- is.list(mylist)
}
return(mylist)
}
It works as expected
> myfun(list1)
Time Series:
Start = 1
End = 100
Frequency = 1
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
[25] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
[49] 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
[73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
[97] 97 98 99 100

loop index in R not increasing by 1

This is a rather simple question: why is this code in R not printing numbers from 1 to 100, but jumps with the value of i? Is there a way to prevent this?
t <-5
for (i in 1:t){
print(20*(i-1)+1:20*i)
}
to get the question closed
t <-5
for (i in 1:t){
print(20*(i-1)+1:20)
}
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#> [1] 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
#> [1] 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
#> [1] 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
#> [1] 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

reprex setting output width

How do I set the width of a reprex output?
Say I have a code like this:
(x <- 1:100)
I get this with reprex::reprex(venue = "so")
(x <- 1:100)
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#> [18] 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
#> [35] 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
#> [52] 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
#> [69] 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
#> [86] 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
How can I increase the width of the output to output something like this
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
[51] 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Possible Solutions
One option that I have found but I find rather "un-tidy" is this (include options(width = ...) at the top of the code. But I don't want it to show up in the output, I'd prefer setting the width in the reprex-call.
options(width = 205)
(x <- 1:100)
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#> [51] 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
reprex() allows for knitr's opts-chunk, but I can't get it working with reprex::reprex(venue = "so", opts_chunk = list(out.width = 205)) (which might be related to #421 as pointed out here (Long lines of text output))
Any better solutions?
reprex has a syntax for setting these options but not including them in the output markdown (see here for examples). In this case:
reprex({
#+ setup, include = FALSE
options(width=205)
#+ actual-reprex-code
(x <- 1:100)
}, venue = 'so')
outputs your desired format:
(x <- 1:100)
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#> [51] 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Created on 2018-09-21 by the reprex package (v0.2.1)

Generate sequence with alternating increments in R? [duplicate]

This question already has answers here:
Get a seq() in R with alternating steps
(6 answers)
Closed 6 years ago.
I want to use R to create the sequence of numbers 1:8, 11:18, 21:28, etc. through 1000 (or the closest it can get, i.e. 998). Obviously typing that all out would be tedious, but since the sequence increases by one 7 times and then jumps by 3 I'm not sure what function I could use to achieve this.
I tried seq(1, 998, c(1,1,1,1,1,1,1,3)) but it does not give me the results I am looking for so I must be doing something wrong.
This is a perfect case of vectorisation( recycling too) in R. read about them
(1:100)[rep(c(TRUE,FALSE), c(8,2))]
# [1] 1 2 3 4 5 6 7 8 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27 28 31 32
#[27] 33 34 35 36 37 38 41 42 43 44 45 46 47 48 51 52 53 54 55 56 57 58 61 62 63 64
#[53] 65 66 67 68 71 72 73 74 75 76 77 78 81 82 83 84 85 86 87 88 91 92 93 94 95 96
#[79] 97 98
rep(seq(0,990,by=10), each=8) + seq(1,8)
You want to exclude numbers that are 0 or 9 (mod 10). So you can try this too:
n <- 1000 # upper bound
x <- 1:n
x <- x[! (x %% 10) %in% c(0,9)] # filter out (0, 9) mod (10)
head(x,80)
# [1] 1 2 3 4 5 6 7 8 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27
# 28 31 32 33 34 35 36 37 38 41 42 43 44 45 46 47 48 51 52 53 54 55 56 57
# 58 61 62 63 64 65 66 67 68 71 72 73 74 75 76 77 78 81 82 83 84 85
# 86 87 88 91 92 93 94 95 96 97 98
Or in a single line using Filter:
Filter(function(x) !((x %% 10) %in% c(0,9)), 1:100)
# [1] 1 2 3 4 5 6 7 8 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27 28 31 32 33 34 35 36 37 38 41 42 43 44 45 46 47 48 51 52 53 54 55 56 57
# [48] 58 61 62 63 64 65 66 67 68 71 72 73 74 75 76 77 78 81 82 83 84 85 86 87 88 91 92 93 94 95 96 97 98
With a cycle: for(value in c(seq(1,991,10))){vector <- c(vector,seq(value,value+7))}

Resources