Interleave and Deinterleave a vector into two new vectors - arrays

Interleaver: Assume we have vector X= randi(1,N) I would like to split the contents of X into two new vectors X1and X2 such that the first element of X is the first element of X1, the first element of X2 is the second element of X, the third element of X is the second element of X1 and the fourth element of X is the second element of X2... etc till the last element of the vector `X.
I have the following idea
X1(1)=X(1);
X2(1)=X(2);
for i=1:length(X)
X1(i)= X(i+2);
end
for j=2:length (X)
X2(i)= X(i+2)
end
My question is: is my method correct? is there a better way to do it?
Deinterleaver
I also have the reverse problem so basically in this case I have X1 and X2 and would like to recover X, how would I efficiently recover X?

I think the terminology in this question is reversed. Interleaving would be to merge two vectors alternating their values:
x1 = 10:10:100;
x2 = 1:1:10;
x = [x1;x2];
x = x(:).';
This is the same as the one-liner:
x = reshape([x1;x2],[],1).';
Deinterleaving would be to separate the interleaved data, as already suggested by David in a comment and Tom in an answer:
y1 = x(1:2:end);
y2 = x(2:2:end);
but can also be done in many other ways, for example inverting the process we followed above:
y = reshape(x,2,[]);
y1 = y(1,:);
y2 = y(2,:);
To verify:
isequal(x1,y1)
isequal(x2,y2)

I was hoping, as well for some cool new one liner, but anyway, following the previous answer you can use the same indexing expression for the assignment.
x = 1:20
x1 = x(1:2:end)
x2 = x(2:2:end)
y = zeros(20,1)
y(1:2:end) = x1
y(2:2:end) = x2

I think it's hard to get a cleaner solution than this:
x = 1:20
x1 = x(1:2:end)
x2 = x(2:2:end)

Just to add another option, you could use the deal function and some precomputed indices. This is basically the same as the answer from Peter M, but collecting the assignments into single lines:
X = randi(10, [1 20]); % Sample data
ind1 = 1:2:numel(X); % Indices for x1
ind2 = 2:2:numel(X); % Indices for x2
[x1, x2] = deal(X(ind1), X(ind2)); % Unweave (i.e. deinterleave)
[X(ind1), X(ind2)] = deal(x1, x2); % Interleave

Related

Problem with for loops and float' object is not a iterable

I was trying to solve a variance problem, but after the for loop I can't the sum values to finally dived by the numbers of items in the list.
lista = [1.86, 1.97, 2.05, 1.91, 1.80, 1.78]
n = len(lista) #NUMBERS OF DATA IN THE LIST
MA = sum(lista)/n #ARITHMETIC MEAN
for x in lista:
y = pow(x - MA, 2) #SUBTRACTION OF ALL DATA BY THE MA, RAISED TO THE POWER OF 2
print(y)
print(sum(y)/n) # AND THAT IS IT, I CAN'T FINISH
I‘m trying to do this work for days and I didn't discovery yet. Is it possible to finish or should I just quit it because there are better ways to solve it?
The result of the variance must be: 0.008891666666666652
PS: I don't want to have to install other programs or libs like pandas or numpy
You are just updating the value of y each time you run the loop so y will be a single element after it reached end of loop.
What you are printing is :
sum(pow(1.78 - MA, 2)/2)
So either you store each value of y inside function in a array of simply do a thing
y=0
y = pow(x-ma, 2)
y += y
I did it again and found the result, thanks Deepak Singh for your help, the asnwer is:
lista = [1.86, 1.97, 2.05, 1.91, 1.80, 1.78]
n = len(lista)
MA = sum(lista)/n
y = 0
for x in lista:
subts = pow(x - MA, 2)
y = (y + subts)
print("Varience:", y/n)

Using plotyy with multiple data sets with different dimensions

I want to produce a plot with two y-axis and apply multiple datasets to one of the axis. For example
[hAx,hLine1,hLine2] = plotyy([x1',x2',x3'],[y1',y2',y3'],x4,y4);
where x1 and y1 are 1000x1-arrays, x2 and y2 are 2000x1-arrays and x3 and y3 are 3000x1-arrays. The range of the arrays is more or less the same. When i try producing this plot, MATLAB gets me an error saying
Error using horzcat Dimensions of matrices being concatenated are not
consistent.
Is there any workaround for this error?
EDIT:
Here's my real code, which is not working:
[hAx,hLine1,hLine2] = plotyy([erg_cm.Time.data,erg_cm.Time.data,t',t'],...
[erg_cm.Car_FxFL.data,erg_cm.Car_FxFR.data,Fx(1,:),Fx(2,:)],...
erg_cm.Time.data,diff);
And my original data:
erg_cm.Time.data is 1x4001
t is 80300x1
erg_cm.Car_FxFL.data is 1x4001
erg_cm.Car_FxFR.data is 1x4001
Fx is 4x80300
diff is 1x4001
Your x and y vectors are column vectors and you're trying to concatenate them horizontally, which you cannot do because they are not the same size. You want to vertically concatenate them:
[hAx,hLine1,hLine2] = plotyy([x1;x2;x3],[y1;y2;y3],x4,y4);
EDIT: This is what I'm testing with
erg_cm.Time.data = rand(1, 4001);
t = rand(80300, 1);
erg_cm.Car_FxFL.data = rand(1, 4001);
erg_cm.Car_FxFR.data = rand(1, 4001);
Fx = rand(4, 80300);
diff = rand(1, 4001);
[hAx,hLine1,hLine2] = plotyy([erg_cm.Time.data,erg_cm.Time.data,t',t'],...
[erg_cm.Car_FxFL.data,erg_cm.Car_FxFR.data,Fx(1,:),Fx(2,:)],...
erg_cm.Time.data,diff);

Can the xor-swap be extended to more than two variables?

I've been trying to extend the xor-swap to more than two variables, say n variables. But I've gotten nowhere that's better than 3*(n-1).
For two integer variables x1 and x2 you can swap them like this:
swap(x1,x2) {
x1 = x1 ^ x2;
x2 = x1 ^ x2;
x1 = x1 ^ x2;
}
So, assume you have x1 ... xn with values v1 ... vn. Clearly you can "rotate" the values by successively applying swap:
swap(x1,x2);
swap(x2,x3);
swap(x3,x4);
...
swap(xm,xn); // with m = n-1
You will end up with x1 = v2, x2 = v3, ..., xn = v1.
Which costs n-1 swaps, each costing 3 xors, leaving us with (n-1)*3 xors.
Is a faster algorithm using xor and assignment only and no additional variables known?
As a partial result I tried a brute force search for N=3,4,5 and all of these agree with your formula.
Python code:
from collections import *
D=defaultdict(int) # Map from tuple of bitmasks to number of steps to get there
N=5
Q=deque()
Q.append( (tuple(1<<n for n in range(N)), 0) )
goal = (tuple(1<<( (n+1)%N ) for n in range(N)))
while Q:
masks,ops = Q.popleft()
if len(D)%10000==0:
print len(D),len(Q),ops
ops += 1
# Choose two to swap
for a in range(N):
for b in range(N):
if a==b:
continue
masks2 = list(masks)
masks2[a] = masks2[a]^masks2[b]
masks2 = tuple(masks2)
if masks2 in D:
continue
D[masks2] = ops
if masks2==goal:
print 'found goal in ',ops
raise ValueError
Q.append( (masks2,ops) )

R: Aggregate on Group 1 and NOT Group 2

I am trying to create two data sets, one which summarizes data by 2 groups which I have done using the following code:
x = rnorm(1:100)
g1 = sample(LETTERS[1:3], 100, replace = TRUE)
g2 = sample(LETTERS[24:26], 100, replace = TRUE)
aggregate(x, list(g1, g2), mean)
The second needs to summarize the data by the first group and NOT the second group.
If we consider the possible pairs from the previous example:
A - X B - X C - X
A - Y B - Y C - Y
A - Z B - Z C - Z
The second dataset should to summarize the data as the average of the outgroup.
A - not X
A - not Y
A - not Z etc.
Is there a way to manipulate aggregate functions in R to achieve this?
Or I also thought there could be dummy variable that could represent the data in this way, although I am unsure how it would look.
I have found this answer here:
R using aggregate to find a function (mean) for "all other"
I think this indicates that a dummy variable for each pairing is necessary. However if there is anyone who can offer a better or more efficient way that would be appreciated, as there are many pairings in the true data set.
Thanks in advance
First let us generate the data reproducibly (using set.seed):
# same as question but added set.seed for reproducibility
set.seed(123)
x = rnorm(1:100)
g1 = sample(LETTERS[1:3], 100, replace = TRUE)
g2 = sample(LETTERS[24:26], 100, replace = TRUE)
Now we have two solutions both of which use aggregate:
1) ave
# x equals the sums over the groups and n equals the counts
ag = cbind(aggregate(x, list(g1, g2), sum),
n = aggregate(x, list(g1, g2), length)[, 3])
ave.not <- function(x, g) ave(x, g, FUN = sum) - x
transform(ag,
x = NULL, # don't need x any more
n = NULL, # don't need n any more
mean = x/n,
mean.not = ave.not(x, Group.1) / ave.not(n, Group.1)
)
This gives:
Group.1 Group.2 mean mean.not
1 A X 0.3155084 -0.091898832
2 B X -0.1789730 0.332544353
3 C X 0.1976471 0.014282465
4 A Y -0.3644116 0.236706489
5 B Y 0.2452157 0.099240545
6 C Y -0.1630036 0.179833987
7 A Z 0.1579046 -0.009670734
8 B Z 0.4392794 0.033121335
9 C Z 0.1620209 0.033714943
To double check the first value under mean and under mean.not:
> mean(x[g1 == "A" & g2 == "X"])
[1] 0.3155084
> mean(x[g1 == "A" & g2 != "X"])
[1] -0.09189883
2) sapply Here is a second approach which gives the same answer:
ag <- aggregate(list(mean = x), list(g1, g2), mean)
f <- function(i) mean(x[g1 == ag$Group.1[i] & g2 != ag$Group.2[i]]))
ag$mean.not = sapply(1:nrow(ag), f)
ag
REVISED Revised based on comments by poster, added a second approach and also made some minor improvements.

merging array elements in Matlab

Suppose x is an array [x1, x2, x3, x4, x5] and we want to merge x2 and x4. This is done by putting their sum in the array and removing x2 and x4 from the array. The output array should look like this: [x1, x2+x4, x3, x5].
Here is one way of doing this in Matlab:
tmp = x(2) + x(4);
x(2) = tmp;
x(4) = tmp;
[m,n] = unique(x,'first');
x(sort(n))
This method works as long as there are no duplicates in the array. Is there any clever Matlab way of doing this for any x without resorting to loops and shifting of array elements after merging values ?
If you want to transform this
x = [x(1) x(2) x(3) ... x(i)... x(j)... x(n)]
into this
x = [x(1) x(2) x(3) ... x(i)+x(j) ... **... x(n)]
where ** is empty and the new x is n-1 elements long, then you should do:
x(i) = x(i)+x(j);
x(j) = [];
no tmp, no sort nor unique.

Resources