Smart way to convert polars to Cartesian coordinates with numpy - math

I have an array of Cartesian coordinates produced from polars in a usual way:
for k in range(0, Phi_term):
for j in range(0, R_term):
X[k,j] = R[j]*np.cos(phi[k]);
Y[k,j] = R[j]*np.sin(phi[k]);
The problem is that the zeroth element of such an array corresponds to the origin of the polar circle. I would like to have an array of the same elements but starting in the top right corner. For example, elements in the current array distribute in the following way (for the upper half):
11 10 9 6 7 8
14 13 12 3 4 5
17 16 15 0 1 2
(imagine it's a circle). What I want to get is the grid starting with the zeroth element:
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
though preserving the values, i.e. the value of the 11th element of the initial array is now the value of the 0th element of the new array.
Is there any smart way to perform such a transformation in numpy?

def quasiCartesianOrder(arr, R_term, Phi_term):
# deal with odd phi count by starting from top of top spike.
rhsOddOffset = 0
if Phi_term % 2 == 1:
rhsOddOffset = R_term
for r in xrange(0, R_term):
yield (Phi_term + 1)/2 * R_term - r - 1
# 'rectangular' section, starting down 11 o'clock and up 1 o'clock.
phiBaseLeft = Phi_term / 2 + rhsOddOffset/R_term
phiBaseRight = Phi_term / 2
for phiLine in xrange(0, Phi_term / 2):
# down 11
base = (phiBaseLeft + phiLine) * R_term - 1
for idx in xrange(base + R_term, base, -1):
yield idx
# up 1
base = (phiBaseRight - phiLine ) * R_term
for idx in xrange(base - R_term, base):
yield idx
Behaviour:
11
10
9
14 13 12 6 7 8
17 16 15 3 4 5
20 19 18 0 1 2
Becomes
0
1
2
3 4 5 6 7 8
9 10 11 12 13 14
15 16 17 18 19 20
Result
11 10 9 14 13 12 6 7 8 17 16 15 3 4 5 20 19 18 0 1 2
The style is a generator, so that you can iterate. If you just want the indices themselves, call list with the returned generator, and you should be able to use that with numpy's index arrays stuff.

Related

R Script to rearrange the elements of a vector by interleaving it

How to write an R-script to initialize a vector with integers, rearrange the elements by interleaving the
first half elements with the second half elements and store in the same vector without using pre-defined function and display the updated vector.
This sounds like a homework question, and it would be nice to see some effort on your own part, but it's pretty straightforward to do this in R.
Suppose your vector looks like this:
vec <- 1:20
vec
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Then you can just do:
c(t(cbind(vec[1:10], vec[11:20])))
#> [1] 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 10 20
This works by joining the two vectors into a 10 x 2 matrix, then transposing that matrix and turning it into a vector.
We may use matrix directly and concatenate
c(matrix(vec, nrow = 2, byrow = TRUE))
-output
[1] 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 10 20
data
vec <- 1:20
Or using mapply:
vec <- 1:20
c(mapply(\(x,y) c(x,y), vec[1:10], vec[11:20]))
#> [1] 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 10 20
We can try this using order + %%
> vec[order((seq_along(vec) - 1) %% (length(vec) / 2))]
[1] 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 10 20
Another way is to use rbind on the 2 halves of the vector, which creates a matrix with two rows. Then, we can then turn the matrix into a vector, which will go through column by column (i.e., 1, 11, 2, 12...). However, this will only work for even vectors.
vec <- 1:20
c(rbind(vec[1:10], vec[11:20]))
# [1] 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 10 20
So, for uneven vectors, we can use order, which will return the indices of the numbers in the two seq_along vectors.
vec2 <- 1:21
order(c(seq_along(vec2[1:10]),seq_along(vec2[11:21])))
# [1] 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 10 20 21

R: take 2 random non-overlapping samples (for same indexes) of length n out of vector of length n as well

Say I have a vector named all_combinations with numbers from 1 to 20.
I need to extract 2 vectors (coding_1 and coding_2) of length equal to number_of_peptide_clusters, which happens to be 20 as well in my current case.
The 2 new vectors should be randomly sampled from all_combinations, so that are not overlapping at each index position.
I do the following:
set.seed(3)
all_combinations=1:20
number_of_peptide_clusters=20
coding_1 <- sample(all_combinations, number_of_peptide_clusters, replace = FALSE)
coding_1
[1] 5 12 7 4 10 8 11 15 17 16 18 13 9 20 2 14 19 1 3 6
coding_2 <- sample(all_combinations, number_of_peptide_clusters, replace = FALSE)
coding_2
[1] 5 9 19 16 18 12 8 6 15 3 13 14 7 2 11 20 10 4 17 1
This is the example that gives me trouble, cause only one number is overlapping at the same index (5 at position 1).
What I would do in these cases is spot the overlapping numbers and resample them out of the list of all overlapping numbers...
Imagine coding_1 and coding_2 were:
coding_1
[1] 5 9 7 4 10 8 11 15 17 16 18 13 12 20 2 14 19 1 3 6
coding_2
[1] 5 9 19 16 18 12 8 6 15 3 13 14 7 2 11 20 10 4 17 1
In this case I would have 5 and 9 overlapping in the same position, so I would resample them in coding_2 out of the full list of overlapping ones [resample index 1 from c(5,9) so that isn't equal to 5, and index 2 so it isn't equal to 9]. So coding_2 would be:
coding_2
[1] 9 5 19 16 18 12 8 6 15 3 13 14 7 2 11 20 10 4 17 1
However, in the particular case above, I cannot use such approach... So what would be the best way to obtain 2 samples of length 20 from a vector of length 20 as well, so that the samples aren't overlapping at the same index positions?
It would be great that I could obtain the second sample coding_2 already knowing coding_1... Otherwise obtaining the 2 at the same time would also be acceptable if it makes things easier. Thanks!
I think the best solution is simply to use a rejection strategy:
set.seed(3)
all_combinations <- 1:20
number_of_peptide_clusters <- 20
count <- 0
repeat {
count <- count + 1
message("Try number ", count)
coding_1 <- sample(all_combinations, number_of_peptide_clusters, replace = FALSE)
coding_2 <- sample(all_combinations, number_of_peptide_clusters, replace = FALSE)
if (!any(coding_1 == coding_2))
break
}
#> Try number 1
#> Try number 2
#> Try number 3
#> Try number 4
#> Try number 5
#> Try number 6
#> Try number 7
#> Try number 8
#> Try number 9
coding_1
#> [1] 18 16 17 12 13 8 6 15 3 5 20 9 11 4 19 2 14 7 1 10
coding_2
#> [1] 5 20 14 2 11 6 7 10 19 8 4 1 15 9 13 17 18 16 12 3
Created on 2020-11-04 by the reprex package (v0.3.0)

R: producing vector with number of times an element appears in sample

I have a homework problem where I have a sample of 30 men, a random sampling of 10 of them:
men
[1] 15 18 14 6 22 17 20 3 16 9
And From them, do 12 random samples and determine how many times each man appears.
The problem statement, verbatim, is "Perform 12 samples of 10 men from a population of size 30 and for each man, record the number
samples in which he appears."
I have attempted a loop for the problem that would produce a vector of 10 elements, each one lined up with the appropriate index.
mtimes<-rep(0,12)
> repeat{
+ mtimes[menind]<-sum(sample(pop1,12,replace = TRUE) == men[menind])
+ menind = menind + 1
+ if (menind == 10){
+ break
+ }
+ }
This resulted in a vector:
mtimes
[1] 0 0 1 0 0 0 0 0 0 0
It seems the 3rd man should not have appeared only once while no one else appeared in the samples.
You can use replicate and table here
set.seed(1)
table(replicate(n = 12, expr = sample(30, size = 10, replace = TRUE)))
# 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
# 3 2 3 5 2 2 5 5 3 3 6 7 4 5 8 2 1 3 2 9 3 7 2 8 3 3 5 3 3 3
I assume that by "men" you mean 1:30.
Another option would be to increase the size of the sample to 10*12 as in
set.seed(1)
table(sample(30, size = 10*12, replace = TRUE))

R creates a different sequence of numbers

Newbie here
I want an equidistant series of numbers between 0 and 20.
Why do I get two different sets of numbers?
0:20
#[1] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
seq(0:20)
#[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Any help would be appreciated. Thank you
Apparently when you pass a vector to seq(), it just prints 1:length(vector), as in
> seq(c(2, 4, 6, 100))
[1] 1 2 3 4
> seq(c('a', 2, mean))
[1] 1 2 3
I don't think that's how you typically use seq(). You'll get the behavior you expect if you pass the first value in the sequence, the last value, and optionally the length of the output or the step size. Better would be
> seq(0, 20)
[1] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
> seq(from = 0, to = 20)
[1] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Look at the seq header from the documentation.
seq(from = 1, to = 1, by = ((to - from)/(length.out - 1)), ...)
To achieve the same behaviour as the first statement you should call it with 2 parameters (from and to).
In your second statement you are calling it with only one parameter and it seems that it is using the length of the given parameter as the number of elements to generate from the default from value, which is 1.
Check this quick example, with a 6-elements vector:
> seq(c(1,4,5,6,2,3))
[1] 1 2 3 4 5 6
In your case, the length of the list 0:20 is 20 and generates 20 numbers from 1: 1,2,...,21

dynamic loop in R

I have a vector x :
x<-rpois(16,lambda=10)
and a lookup table named u3 :
minx<-min(x)
maxx<-max(x)
dg<-maxx-minx
k<-5
sa<-ceiling(dg/k)
u1=data.frame(seq(minx,maxx,sa))
colnames(u1)<-"x"
u2<-NULL
for (i in 1:k)
{
u2[i]<-u1[i,] + sa-1
}
u2<-as.data.frame(u2)
colnames(u2)<-"y"
u3<-cbind(u1,u2)
for(i in 1:nrow(u2))
{
u3$range[i]<-paste(u1[i,],u2[i,],sep="-")
}
print(u3)
my u3 data.frame like :
x y range
1 3 5 3-5
2 6 8 6-8
3 9 11 9-11
4 12 14 12-14
5 15 17 15-17
I want to do a calculation here:
I want to every x vector look in u3 data frame variables in colums 1,2
and then if condition true,so if x values are in range,count the x values which are in the range of u3 dataframe and write the count to u3 dataframe as a new column.
something like this :
count=0
for(i in 1:length(x))
{
for(j in 1:nrow(u3))
{
u3$count[j]<-if(x[i]>=u3[j,1] & x[i]<=u3[j,2]) {count=count + 1}
}
}
but i can't make it.
Do you have an idea about it ? How can I deal such a problem ?
I dont know how to tell R to look dynamically to lookup table and write the count of it.
I want such a desired output
x y range count
1 3 5 3-5 2
2 6 8 6-8 5
3 9 11 9-11 1
4 12 14 12-14 4
5 15 17 15-17 3
Thank you
with set.seed(0)
x
[1] 13 8 14 14 11 14 12 11 9 14 11 8 2 8 10 7
u3
x y range
1 2 4 2-4
2 5 7 5-7
3 8 10 8-10
4 11 13 11-13
5 14 16 14-16
cbind(u3,data.frame(table(findInterval(x,u3$x))))
x y range Var1 Freq
1 2 4 2-4 1 1
2 5 7 5-7 2 1
3 8 10 8-10 3 5
4 11 13 11-13 4 5
5 14 16 14-16 5 4
Keep in mind, I used findInterval(x,u3$x) it only works for your example because your groupings are (x,y] ie (x inclusive, y non-inclusive)

Resources