I'm looking for something in Julia like a comprehension but for a matrix instead of a vector. If i have some single-variable function f(x) and I want an array that is filled with f(i) for i in 1..10, I can do this:
[f(i) for i = 1:10]
If I have some two-variable function g(i,j) and I want a matrix from i=[1,10]; j=[1,10] filled with the function I can do this:
M = zeros (10,10)
for i in 1:10
for j in 1:10
M[i,j] = g(i,j)
end
end
Is there some shortcut that allows me to express that in a shorter way and without wasting time allocating all that zeros?
Just use a multidimensional comprehension directly:
julia> g(x,y) = 2x+y
g (generic function with 1 method)
julia> [g(i,j) for i=1:10, j=1:10]
10x10 Array{Int64,2}:
3 4 5 6 7 8 9 10 11 12
5 6 7 8 9 10 11 12 13 14
7 8 9 10 11 12 13 14 15 16
9 10 11 12 13 14 15 16 17 18
11 12 13 14 15 16 17 18 19 20
13 14 15 16 17 18 19 20 21 22
15 16 17 18 19 20 21 22 23 24
17 18 19 20 21 22 23 24 25 26
19 20 21 22 23 24 25 26 27 28
21 22 23 24 25 26 27 28 29 30
This works for any number of dimensions, by adding variable ranges at the end.
Related
I want to select a control group from one data frame based of matching the age from a second data frame. As an example I have subject.df
subject.df
id age
1 1 55
2 2 62
3 3 73
4 4 54
5 5 66
I'd like to subset control.df based off of matching the age directly on a 1 to 1 matching from the subject.df dataframe.
control.df
id age
6 6 66
7 7 71
8 8 80
9 9 51
10 10 55
11 11 56
12 12 77
13 13 62
14 14 64
15 15 73
16 16 67
17 17 54
18 18 75
19 19 77
20 20 78
21 21 53
22 22 64
23 23 83
24 24 61
25 25 77
I'm fairly new to R. In the past I've used Matlab and in this instance would use a for loop to iterate over the control.df dataframe, but I've been told that R doesn't always like for loops and that it can be computationally difficult in R.
In the end I'll be doing this on a much larger data set where the subject group is around 250 and the control group is more than 40K so I know that 1:1 matching is possible.
Is there a way to sum pairwise in Octave?
If for example, I have a 10-row by 4 column. I want a new 10 row by 2 column, where each column is the sum of the pairs.
ex.
[ 1 2 3 4
2 3 4 5
...
]
=> [ 3 7
5 9
...
]
I know how to accomplish this using for loops and accumarray etc, but I'm just not sure if there's a way to do it that is completely vectorized.
Here are a few more options.
Given:
a = reshape(1:40, 10, 4)
a =
1 11 21 31
2 12 22 32
3 13 23 33
4 14 24 34
5 15 25 35
6 16 26 36
7 17 27 37
8 18 28 38
9 19 29 39
10 20 30 40
Keep it simple
b = [sum(a(:,1:2),2) sum(a(:,3:4),2)]
b =
12 52
14 54
16 56
18 58
20 60
22 62
24 64
26 66
28 68
30 70
Squeeze a little
b = squeeze(sum(reshape(a, [], 2, 2), 2))
b =
12 52
14 54
16 56
18 58
20 60
22 62
24 64
26 66
28 68
30 70
Or, my personal favorite...
Mathemagic
b = a * [1 1 0 0; 0 0 1 1].'
b =
12 52
14 54
16 56
18 58
20 60
22 62
24 64
26 66
28 68
30 70
Perhaps someone comes with a better idea:
a = [1 2 3 4; 2 3 4 5]
b = reshape (sum (reshape (a.', 2, [])), [], rows(a)).'
gives
b =
3 7
5 9
This is an algorithmic problem. I can't seem to find a way to compare relative positions of 2 cubes in a rubix cube.
I've numbered all the 20 cubes in my program. and I'm using their this coordinate system, but now that I wanted to model two cubes in relative position I'm having trouble.
For example, say I saw the two cubes I'm watching in position 8 and 10, then later I saw them in position 12 and 13, well in both situations they're both on the same face of the cube, and they're both across from each other, not adjacent. Relatively speaking, that's the same representation of their location.
(By the way I'm only concerned with the "edge cubes" at this point, that's not the corners, so: 8 10 9 11 12 13 14 15 16 17 18 19 positions).
So anyway I thought if I listed every position in relation to each staring point, using the same algorithm to list each one, then I could compare the indexes and if they were the same, the relative position would be the same (but I was wrong, I might be on the right track, but it doesn't always work):
08 10 18 16 12 13 14 15 09 11 19 17
09 11 19 17 13 14 15 12 10 08 16 18
10 18 16 08 14 15 12 13 11 09 17 19
11 19 17 09 15 12 13 14 08 10 18 16
12 13 14 15 11 19 17 09 16 08 10 18
13 14 15 12 08 16 18 10 17 09 11 19
14 15 12 13 09 17 19 11 18 10 08 16
15 12 13 14 10 18 16 08 19 11 09 17
16 08 10 18 19 17 09 11 13 12 15 14
17 09 11 19 16 18 10 08 14 13 12 15
18 16 08 10 17 19 11 09 15 14 13 12
19 17 09 11 18 16 08 10 12 15 14 13
Consider the following two positions: cube A is at potion 19 and cube b is at 16. they're adjacent on the bottom level. Here's "19" row and it's indices to 16:
0 1 2 3 4 5
19 17 09 11 18 16 08 10 12 15 14 13
Now compare that to the relative position of the cube c and d at 13 and 9. C and D are adjacent on the right side, so they should have the same relative position. But my method doesn't determine that.
0 1 2 3 4 5 6 7 8 9
13 14 15 12 08 16 18 10 17 09 11 19
index 6 is not equal to index 9. Anyway that was my best approach and it took all day to come up with.
Does anyone have any other strategies that come to mind for calculating / expressing relative position between two locations on a cube?
Thanks very much for your help, and consideration on this topic!
There are two problems here:
I think you made a mistake when you calculated the relative positions from cube 13. I get:
0 1 2 3 4 5 6 7 8 9 10 11
13 14 15 12 17 09 11 19 08 16 18 10
This lines up with the other one, so cube 9 occurs at position 5. Compare this with the first row:
0 1 2 3 4 5 6
19 17 09 11 18 16 08 10 12 15 14 13
As required, cube 16 also occurs at position 5 (I think you mixed something up in your question. You mention index 6 when you mean 5. You number the indexes up to 6, but at position 6 there is cube 8, not cube 16. Please check that again).
The second problem is that given only a cube position without a reference cube for the orientation, there are two ways to number the cubes. Since your cube is not colored, you can rotate the cube by 180 degrees and come to another numbering for the reference cubes. Given that the relative positions for cube 19 are correct, I can also number the relative positions for cube 13 like this:
0 1 2 3 4 5 6 7 8 9 10 11
13 12 15 14 08 16 18 10 17 09 11 19
Note that this is close to your version but indexes 1 to 3 are in a different order. I think you were not consistent in the way you looked at the cube.
The main problem already becomes apparent in this paragraph:
For example, say I saw the two cubes I'm watching in position 8 and
10, then later I saw them in position 12 and 13, well in both
situations they're both on the same face of the cube, and they're both
across from each other, not adjacent. Relatively speaking, that's the
same representation of their location.
For every cube, there are two other cubes being on the same face and across from each other. To eliminate this ambiguity, you have to take orientations into account or reduce the number of relative positions (e.g. index 1 and 3 in your current scheme would denote the same relative position).
When I use the imrotate function of MATLAB, output image has missing parts which are filled with zeros.
Can I somehow make it so the triangles in the corners (i.e. the missing parts) are filled with the opposite edge of the image? So it will be like I have tiled the image with 8 neighbors around itself, and then rotated and cropped the bigger image?
Thanks for any help,
I think that the best (and most memory efficient) way of doing this, would be to use interp2 to sample the original image at the new pixel centers (the original pixel centers "rotated" by the opposite of the desired angle). And then to use mod on these sample points to ensure that they fall within the dimension of the original image. And the added benefit of mod is that the new x,y coordinates that are out of range, simply "wrap around" to the other side of the image.
% Load some sample image
load mri
im = double(D(:,:,12));
[rows, cols] = size(im);
% The original pixel centers
[xx,yy] = meshgrid(1:cols, 1:rows);
% Setup the rotation matrix
theta = pi/4;
R = [cos(-theta), -sin(-theta);
sin(-theta), cos(-theta)];
% Center of Rotation (center of the image)
center = [cols/2, rows/2];
% Determine the new pixel centers (rotated)
xy = bsxfun(#minus, [xx(:), yy(:)], center) * R;
xy = bsxfun(#plus, xy, center);
% Mod these using the dimensions of the image to "wrap" around
x = mod(xy(:,1) - 1, cols - 1) + 1;
y = mod(xy(:,2) - 1, rows - 1) + 1;
% Sample the original image at the new pixel centers
im2 = interp2(xx, yy, im, x, y);
im2 = reshape(im2, [rows, cols])
Rotation = 45 degrees
This will work with any arbitrary aspect ratio (below is an image demonstrating the issue brought up by #BlackAdder where a repmat [3,3] wouldn't work due to the image being tall and narrow).
Rotation = 90 degrees
This also has the added benefit that it doesn't rely on the Image Processing Toolbox.
The most direct way, using the Image Processing Toolbox, is to use padarray. Given an image:
>> img = reshape(1:25, 5, 5)
img =
1 6 11 16 21
2 7 12 17 22
3 8 13 18 23
4 9 14 19 24
5 10 15 20 25
Then you can replicate the image on all sides:
>> padarray(img, size(img), 'circular')
ans =
1 6 11 16 21 | 1 6 11 16 21 | 1 6 11 16 21
2 7 12 17 22 | 2 7 12 17 22 | 2 7 12 17 22
3 8 13 18 23 | 3 8 13 18 23 | 3 8 13 18 23
4 9 14 19 24 | 4 9 14 19 24 | 4 9 14 19 24
5 10 15 20 25 | 5 10 15 20 25 | 5 10 15 20 25
--------------------------------------------------------------------------
1 6 11 16 21 | 1 6 11 16 21 | 1 6 11 16 21
2 7 12 17 22 | 2 7 12 17 22 | 2 7 12 17 22
3 8 13 18 23 | 3 8 13 18 23 | 3 8 13 18 23
4 9 14 19 24 | 4 9 14 19 24 | 4 9 14 19 24
5 10 15 20 25 | 5 10 15 20 25 | 5 10 15 20 25
--------------------------------------------------------------------------
1 6 11 16 21 | 1 6 11 16 21 | 1 6 11 16 21
2 7 12 17 22 | 2 7 12 17 22 | 2 7 12 17 22
3 8 13 18 23 | 3 8 13 18 23 | 3 8 13 18 23
4 9 14 19 24 | 4 9 14 19 24 | 4 9 14 19 24
5 10 15 20 25 | 5 10 15 20 25 | 5 10 15 20 25
(Lines added to show the original matrix in the center and the padded copies.) Once you're done rotating, you can crop the middle of the matrix for your final image.
Note that this method also works on 3-channel images.
As #Suever and #BlackAdder note in the comments, this padding can be insufficient for images with large aspect ratio (greater than 25.456:9), particularly for rotations near odd multiples of 45°. You can make the padding more accurate by calculating the maximum you might need.
s = size(img);
s = s(1:2); % account for multi-channel images
maxext = sqrt(s * s.'); % calculate length of image diagonal
padsize = ceil((maxext - s)/2); % find amount of padding needed for each side
padarray(img, padsize, 'circular');
I've read this SO question on how to rotate a two-dimensional array many times, and I was curious as to how you could expand this situation to work with a section of a two-dimensional array. I've thought about it for a while, and I can't seem to come up with a good equation. Essentially what I'm wanting to do is something like this:
1 2 3 4 5 6 13 7 1 4 5 6
7 8 9 10 11 12 14 8 2 10 11 12
13 14 15 16 17 18 15 9 3 16 17 18
19 20 21 22 23 24 ----> 19 20 21 22 23 24
25 26 27 28 29 30 25 26 27 28 29 30
31 32 33 34 35 36 31 32 33 34 35 36
I'm writing this in Ruby, currently, but I don't particularly care what language the solution to this kind of problem would be. I'm just curious as to how you'd go about solving this kind of problem.
Edit: To add some more specifics, the basic parameters for a function that could do this would be something that looked like this
def rotate(array, times=1, x=0, y=0, len=nil)
...
end
Check this question : How do you rotate a two dimensional array?
there is a simple way :
a 2-dim array, use
transpose.map &:reverse
Something like that?
def rotate a,len,ii=0,jj=0,t=1
t.times do
a = a.map.with_index do |line,i|
line.map.with_index do |e,j|
(ii...(ii+len))===i && (jj...(jj+len))===j ?
a[ii+jj+len-j-1][jj+i-ii] : e
end
end
end
a
end
t = (1..6).map{|i|(1..6).map{|j|j+6*i-6}}
t.each { |i| p i }
rotate(t,3,2,1).each { |i| p i }
rotate(t,6).each { |i| p i }
rotate(t,3,2,1,4).each { |i| p i }
rotate(t,6,0,0,4).each { |i| p i }
rotate(t,2,2,2,3).each { |i| p i }