SAS Many to Many Merge - join

Below is the data i have an am trying to merge. I have also included the expected output but my code is only merging on the first match.
I have Data in Beta that is updated the following week. For instance for 9/6 week (it updates on 9/14 per say). This data changes week to week and as it updates Alpha table starts pulling in the next week. Beta only contains a monday date so i have dateparted it to get the week date to match this with every day of that week which is stored in beta. So since 9/6wk is 22592 i want to match with every day of that week stored in alpha so that would be 9/6-9/10. So i have date parted those dates as well so it displays which week they are thus beta should match with dates 9/6-9/10 in this example.
Note i do not expect or what to match with future weeks but i still need to keep the content. So i just want to match the previous week data in Beta with the previous weeks data in Alpha.
Beta table: only houses previous weeks data
alpha table: houses previous week + current week data.
I want to take the data in B
Table Alpha- This table stores the main info including the dates of each week mon-friday. Note this monday was not included due to holiday.
ID
PKG
Week
IS
SE
date
70
17AB
22529
Y
N
9/7/2021
70
17AB
22529
Y
N
9/8/2021
70
17AB
22529
Y
N
9/9/2021
70
17AB
22529
Y
N
9/10/2021
70
17AX
22536
-
N
9/13/2021
70
12AX
22536
-
N
9/14/2021
70
17AX
22536
-
N
9/15/2021
Table Beta- this table stores 2 extra columns of data relevant to table alpha. However it contains no dates but the Monday date for the previous week and info relevant to that.
ID
PKG
Week
add1
Add2
Monday
70
17AB
22529
Y
N
9/6/2021
70
17AX
22529
Y
N
9/6/2021
Data want
ID
PKG
Week
IS
SE
add1
add2
date
70
17AB
22529
Y
N
Y
N
9/7/2021
70
17AB
22529
Y
N
Y
N
9/8/2021
70
17AB
22529
Y
N
Y
N
9/9/2021
70
17AB
22529
Y
N
Y
N
9/10/2021
70
17AX
22529
Y
N
Y
N
9/7/2021
70
17AX
22529
Y
N
Y
N
9/8/2021
70
17AX
22529
Y
N
Y
N
9/9/2021
70
17AX
22529
Y
N
Y
N
9/10/2021
70
17AX
22536
-
N
9/14/2021
70
12AX
22536
-
N
9/15/2021
70
17AX
22536
-
N
9/16/2021
My attempt:
DATA Alpha; drop monday;
Merge Alpha (in=a) Beta (in=b);
by id pkg week;
if a;
run;
i tried this because i need to keep everything in table A but want to add the info in table B. However its only matching on the first one.

Your code works fine. But since you include the WEEK variable as a key for the merge the second ID/PKG combination from ALPHA will not match any observations from BETA since the week value in ALPHA is one week after the week value in BETA.
With your sample data you only need to use ID and PKG to merge ALPHA and BETA.
data alpha;
input ID $ PKG $ WeekA :yymmdd. IS $ SE $ DATE :yymmdd.;
format weekA date yymmdd10.;
cards;
70 17AB 2021-09-06 Y N 2021-09-07
70 17AB 2021-09-06 Y N 2021-09-08
70 17AB 2021-09-06 Y N 2021-09-09
70 17AB 2021-09-06 Y N 2021-09-10
70 17AX 2021-09-13 - N 2021-09-13
70 17AX 2021-09-13 - N 2021-09-14
70 17AX 2021-09-13 - N 2021-09-15
;
data beta;
input ID $ PKG $ WeekB :yymmdd. Add1 Add2 Monday :yymmdd.;
format weekB monday yymmdd10.;
cards;
70 17AB 2021-09-06 Y N 2021-09-06
70 17AX 2021-09-06 Y N 2021-09-06
;
data want;
merge alpha beta;
by id pkg ;
run;
Results:
ID PKG WeekA IS SE DATE WeekB Add1 Add2 Monday
70 17AB 2021-09-06 Y N 2021-09-07 2021-09-06 Y N 2021-09-06
70 17AB 2021-09-06 Y N 2021-09-08 2021-09-06 Y N 2021-09-06
70 17AB 2021-09-06 Y N 2021-09-09 2021-09-06 Y N 2021-09-06
70 17AB 2021-09-06 Y N 2021-09-10 2021-09-06 Y N 2021-09-06
70 17AX 2021-09-13 - N 2021-09-13 2021-09-06 Y N 2021-09-06
70 17AX 2021-09-13 - N 2021-09-14 2021-09-06 Y N 2021-09-06
70 17AX 2021-09-13 - N 2021-09-15 2021-09-06 Y N 2021-09-06
If the goal is to find the values of ADD1 and ADD2 from the most recent DATE in BETA then perhaps you really want to interleave the observations by date instead of merging. Then even if the DATE in BETA is a week before the DATE in ALPHA the values of ADD1 and ADD2 will be copied onto the observations from ALPHA.
Make new variables to retain the values of ADD1 and ADD2 from the observations read from BETA onto the following observations for ALPHA.
data alpha;
input ID $ PKG $ IS $ SE $ DATE :yymmdd.;
format date yymmdd10.;
cards;
70 17AB Y N 2021-09-07
70 17AB Y N 2021-09-08
70 17AB Y N 2021-09-09
70 17AB Y N 2021-09-10
70 17AX - N 2021-09-13
70 17AX - N 2021-09-14
70 17AX - N 2021-09-15
;
data beta;
input ID $ PKG $ DATE :yymmdd. Add1 Add2 ;
format DATE yymmdd10.;
cards;
70 17AB 2021-09-06 Y N
70 17AX 2021-09-06 Y N
;
data want;
set beta(in=inb) alpha(in=ina);
by id pkg date;
if inb then do;
retain _add1 _add2;
_add1=add1;
_add2=add2;
rename _add1=add1 _add2=add2;
drop add1 add2;
end;
if ina then output;
if last.pkg then call missing(_add1,_add2);
run;
Results
ID PKG DATE IS SE add1 add2
70 17AB 2021-09-07 Y N Y N
70 17AB 2021-09-08 Y N Y N
70 17AB 2021-09-09 Y N Y N
70 17AB 2021-09-10 Y N Y N
70 17AX 2021-09-13 - N Y N
70 17AX 2021-09-14 - N Y N
70 17AX 2021-09-15 - N Y N

So as Tom mentioned what I had does work. For some reason it was bugging out when I was running it yesterday. I think the issue was in my code I had my by variables in the wrong order when I typed them wrong on here. A silly mistake but none the less thank you Tom for the help!
DATA Alpha; drop monday;
Merge Alpha (in=a) Beta (in=b);
by id pkg week;
if a;
run;

Related

Solving Equations with (wx)Maxima: Control stack exhausted

Solving Equations with (wx)Maxima: Control stack exhausted
I'm trying to solve equations with (wx)Maxima: formulate the equation, then let it insert the variables and solve the equation for the missing variable. But I'm having a hard time. Somehow it's having problems in the last line:
Control stack exhausted (no more space for function call frames).
This is probably due to heavily nested or infinitely recursive function
calls, or a tail call that SBCL cannot or has not optimized away.
That's my code:
kill(all);
load(physical_constants);
load(unit);
setunits([kg,m,s,N]);
showtime: false;
α: 30*%pi/180;
/*α: 30*°;*/
masse: 1000*kg;
g: 9.80665*m/(s*s);
b: 0.3*m;
B: 0.5*m;
L: 0.1*m;
F_g: masse*g;
F_H: masse * g;
kill(S, x);
S: solve(0=F_H-2*x*sin(α), x);
S: assoc(x, S);
kill(H, x);
H: solve(0=-F_g+2*x, x);
H: assoc(x, H);
kill(Ly, x);
Ly: solve(tan(α)=x/(B/2), x);
Ly: assoc(x, Ly);
kill(FN, x);
FN: solve(0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly, x);
FN: assoc(x, FN);
If I calculate it "directly", it works though:
kill(all);
load(physical_constants);
load(unit);
setunits([kg,m,s,N]);
showtime: false;
kill(FN, x);
FN: solve([α=30*%pi/180, H=196133/40*N,
B=0.5*m, L=0.1*m,
Ly=sqrt(3)/12*m, S=196133/20*N,
0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly],
[x, α, H, B, L, Ly, S]);
FN: assoc(x, FN[1]);
FN: float(FN);
(FN) 1934473685/128529*N
Unfortunately the unit package has not been updated in some time. I'll suggest to use instead the package ezunits, in which dimensional quantities are represented with a back quote. To solve equations, try dimensionally which goes through some gyrations to help other functions with dimensional quantities, e.g. dimensionally (solve (...)). (Note that dimensionally isn't documented, I'm sorry for the shortcoming.)
I've modified your program a little to remove some unneeded stuff and also to use rational numbers instead of floats; Maxima is generally more comfortable with rationals and integers than with floats. Here is the program:
linel: 65 $
load(ezunits) $
α: 30*%pi/180;
masse: 1000`kg;
g: rationalize(9.80665)`m/(s*s);
b: 3/10`m;
B: 5/10`m;
L: 1/10`m;
F_g: masse*g;
F_H: masse * g;
S: dimensionally (solve(0=F_H-2*x*sin(α), x));
S: assoc(x, S);
Ly: dimensionally (solve(tan(α)=x/(B/2), x));
Ly: assoc(x, Ly);
FN: dimensionally (solve(0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly, x));
FN: assoc(x, FN);
subst (x = S, F_H-2*x*sin(α));
subst (x = Ly, tan(α)=x/(B/2));
subst (x = FN, H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly);
ratsimp (expand (%));
and here is the output I get. Note that I substituted the solutions back into the equations to verify them. It looks like it worked as expected.
(%i2) linel:65
(%i3) load(ezunits)
(%i4) α:(30*%pi)/180
%pi
(%o4) ---
6
(%i5) masse:1000 ` kg
(%o5) 1000 ` kg
(%i6) g:rationalize(9.80665) ` m/(s*s)
5520653160719109 m
(%o6) ---------------- ` --
562949953421312 2
s
(%i7) b:3/10 ` m
3
(%o7) -- ` m
10
(%i8) B:5/10 ` m
1
(%o8) - ` m
2
(%i9) L:1/10 ` m
1
(%o9) -- ` m
10
(%i10) F_g:masse*g
690081645089888625 kg m
(%o10) ------------------ ` ----
70368744177664 2
s
(%i11) F_H:masse*g
690081645089888625 kg m
(%o11) ------------------ ` ----
70368744177664 2
s
(%i12) S:dimensionally(solve(0 = F_H-2*x*sin(α),x))
690081645089888625 kg m
(%o12) [x = ------------------ ` ----]
70368744177664 2
s
(%i13) S:assoc(x,S)
690081645089888625 kg m
(%o13) ------------------ ` ----
70368744177664 2
s
(%i14) Ly:dimensionally(solve(tan(α) = x/(B/2),x))
1
(%o14) [x = --------- ` m]
4 sqrt(3)
(%i15) Ly:assoc(x,Ly)
1
(%o15) --------- ` m
4 sqrt(3)
(%i16) FN:dimensionally(solve(0 = (H*B)/2-x*(L+Ly)
+(S*sin(α)*B)/2
+S*cos(α)*Ly,x))
1 1
(%o16) [x = (----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2
+ 1150136075149814375 3 ` kg m)]
(%i17) FN:assoc(x,FN)
1 1
(%o17) (----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2
+ 1150136075149814375 3 ` kg m)
(%i18) subst(x = S,F_H-2*x*sin(α))
kg m
(%o18) 0 ` ----
2
s
(%i19) subst(x = Ly,tan(α) = x/(B/2))
1 1
(%o19) ------- = -------
sqrt(3) sqrt(3)
(%i20) subst(x = FN,(H*B)/2-x*(L+Ly)+(S*sin(α)*B)/2+S*cos(α)*Ly)
1 1
(- ---------) - --
4 sqrt(3) 10 1
(%o20) ((----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2 H
+ 1150136075149814375 3 ` kg m) + -) ` m
4
2
690081645089888625 kg m
+ ------------------ ` -----
281474976710656 2
s
(%i21) ratsimp(expand(%))
2
kg m
(%o21) 0 ` -----
2
s
EDIT. About converting kg*m/s^2 to N, you can apply the double back quote operator. For example:
(%i25) F_g `` N
690081645089888625
(%o25) ------------------ ` N
70368744177664
By the way, to convert back to floats, you can apply float:
(%i26) float(%)
(%o26) 9806.649999999998 ` N
Converting FN to N is a little more involved, since it's a more complex expression, especially because of H which doesn't have units attached to it yet. Some inspection seems to show the units of H must be kg*m/s^2. I'll apply declare_units to say that's what are the units of H. Then I'll convert FN to N.
(%i27) declare_units(H,(kg*m)/s^2)
kg m
(%o27) ----
2
s
(%i28) FN `` N
351843720888320 sqrt(3) qty(H)
(%o28) (-----------------------------------------
140737488355328 sqrt(3) + 351843720888320
3/2
1150136075149814375 3
+ -----------------------------------------) ` N
140737488355328 sqrt(3) + 351843720888320
(%i29) float(%)
(%o29) (1.023174629940149 qty(H) + 10033.91548470256) ` N
The notation qty(H) represents the unspecified quantity of H. One could also just subst(H = 100 ` kg*m/s^2, FN) (or any quantity, not just 100) and go from there.

Why is Maxima failing to give a solution?

I have a function in Maxima I am differentiating then attempting to find the value at which this is zero. When I use solve(), however, I am not given a solution. Why is this, and how can I work around it?
(%i1) f(x):=(-5*(x^4+5*x^3-3*x))/(x^2+1);
(%o1) f(x):=((-5)*(x^4+5*x^3+(-3)*x))/(x^2+1)
(%i2) df(x):=''(diff(f(x), x));
(%o2) df(x):=(10*x*(x^4+5*x^3-3*x))/(x^2+1)^2-(5*(4*x^3+15*x^2-3))/(x^2+1)
(%i3) solve(df(x), x);
(%o3) [0=2*x^5+5*x^4+4*x^3+18*x^2-3]
The function solve is not too strong; there are many problems it can't solve. A stronger version is under development. In the meantime, try the add-on package to_poly_solve. Here's what I get:
(%i1) df(x) := (10*x*(x^4+5*x^3-3*x))/(x^2+1)^2-(5*(4*x^3+15*x^2-3))/(x^2+1) $
(%i2) load (to_poly_solve) $
(%i3) to_poly_solve (df(x), x);
(%o3) %union([x = - 2.872468527640942], [x = - 0.4194144025323134],
[x = 0.3836388367122223], [x = 0.2041221431132173 - 1.789901606296292 %i],
[x = 1.789901606296292 %i + 0.2041221431132173])
Something which is maybe a little surprising is that to_poly_solve has returned a numerical solution instead of exact or symbolic. Tracing allroots shows that to_poly_solve has constructed a quintic equation and punted it to allroots. Since the general quintic doesn't have a solution in terms of radicals, and even in special cases it's probably very messy, maybe it's most useful to have a numerical solution anyway.
Try plot2d(df(x), [x, -3, 1]) to visualize the real roots returned above.
You can try to find a numerical solution. I don't know why solve does not try this. Either you take the ouput of aolveor you do hte folölowing:
(%i1) f(x):=(-5*(x^4+5*x^3-3*x))/(x^2+1);
4 3
(- 5) (x + 5 x + (- 3) x)
(%o1) f(x) := ---------------------------
2
x + 1
(%i2) df(x):=''(diff(f(x), x));
4 3 3 2
10 x (x + 5 x - 3 x) 5 (4 x + 15 x - 3)
(%o2) df(x) := ---------------------- - --------------------
2 2 2
(x + 1) x + 1
Bring it to a common denominator and extract the numerator:
(%i3) xthru(df(x));
4 3 2 3 2
10 x (x + 5 x - 3 x) - 5 (x + 1) (4 x + 15 x - 3)
(%o3) ------------------------------------------------------
2 2
(x + 1)
(%i4) num(%);
4 3 2 3 2
(%o4) 10 x (x + 5 x - 3 x) - 5 (x + 1) (4 x + 15 x - 3)
use allsrootsto find the roots of a polynomial numerically
(%i5) allroots(%);
(%o5) [x = 0.3836388391066617, x = - 0.4194143906217701,
x = 1.789901606296292 %i + 0.2041221431132174,
x = 0.2041221431132174 - 1.789901606296292 %i, x = - 2.872468734711326]
skip the complex solutions
(%i6) sublist(%,lambda([t],imagpart(rhs(t))=0))
;
(%o6) [x = 0.3836388391066617, x = - 0.4194143906217701,
x = - 2.872468734711326]

Substitute variable in Maxima

newbie Maxima question
I have a transfer function in Maxima
E1 : y = K_i*s/(s^2 + w^2);
I'd like to have the closed-form of the equation affter applying the bilinear transform
E2 : s = (2/Ts*(z-1)/(z+1));
I would like to get the transfer function for z, by substituing s by equation E2. How should I proceed?
Regards
Note that subst can apply one or more substitutions stated as equations. In this case, try subst(E2, E1).
That will probably create a messy result -- you can simplify it somewhat by applying ratsimp to the result.
Here's what I get from that.
(%i2) E1 : y = K_i*s/(s^2 + w^2);
K_i s
(%o2) y = -------
2 2
w + s
(%i3) E2 : s = (2/Ts*(z-1)/(z+1));
2 (z - 1)
(%o3) s = ----------
Ts (z + 1)
(%i4) subst (E2, E1);
2 K_i (z - 1)
(%o4) y = ------------------------------
2
4 (z - 1) 2
Ts (z + 1) (------------ + w )
2 2
Ts (z + 1)
(%i5) ratsimp (%);
2
2 K_i Ts z - 2 K_i Ts
(%o5) y = -----------------------------------------------
2 2 2 2 2 2 2
(Ts w + 4) z + (2 Ts w - 8) z + Ts w + 4

Torch - Randomly choose dimension of tensor to slice

I have a torch tensor of size (1 x n x n x n) and I would like to randomly choose one of the last 3 dimensions to randomly slice at s and then do. For example it could output the below tensors with equal probability;
(1 x s x n x n)
(1 x n x s x n)
(1 x n x n x s)
I realise I could just do a few if else statements but I am curious if there is a "neater" option using a function like torch.random(1,4) to select the dimension.
assuming that you want to narrow a block of s elements randomly, out of n elements.
Let's use :narrow.
n = 100
s = 20
x = torch.randn(1, n, n, n)
y = x:narrow(torch.random(2, 4), torch.random(1, n - s + 1), s)

Algorithm to add two digits to the end of a number to calculate a specific modulus?

So, lets say I have a number 123456. 123456 % 97 = 72. How can I determine what two digits need to be added to the end of 123456 such that the new number % 97 = 1? Note--it must always be two digits.
For example, 12345676 % 97 = 1. In this case, I need to add the digits "76" to the end of the number.
(This is for IBAN number calculation.)
x = 123456
x = x * 100
newX = x + 1 + 97 - (x % 97)
Edit: put the 100 in the wrong place
You calc the modulo of 12345600 to 97 and add (97 - that + 1) to that number.
So you get what RoBorg explained whay cleaner above :)
This is the equation that that you need
X = Y -(Number*100 mod y) - 1
where:
Number = 123456
Y = 97
X the number you need
Let’s say we have to receive the number containing 12 digits.
Step 1:
Write any random number of 10 digits, i.e. 2 digits less than needed, e.g. 1234567890 – this is X
Step 2:
X * 100 = 123456789000.
‘123456789000’ - this is Y
Step 3:
Y / 97 = '1272750402.061856'.
'06' – this is Z
Step 4:
97 – Z + 1 = 92.
'92' – this is W
Step 5:
Final Deal Number is X followed by W, i.e. '123456789092'
Examples of accepted numbers:
100000000093
100000000190
100000000287
Etc.
Modulo arithmetic is really not that different from regular arithmetic. The key to solving the kind of problem that you're having is to realize that what you would normally do to solve that problem is still valid (in what follows, any mention of number means integer number):
Say you have
15 + x = 20
The way that you solve this is by realizing that the inverse of 15 under regular addition is -15 then you can write (exploiting commutativity and associativity as we naturally do)
15 + x + (-15) = (15 + (-15)) + x = 0 + x = x = 20 + (-15) = 5
so that your answer is x = 5
Now on to your problem.
Say that N and M are known, and you're looking for x under addition modulo k:
( N + x ) mod k = M
First realize that
( N + x ) mod k = ( ( N mod k ) + ( x mod k ) ) mod k
and for the problem to make sense
M mod k = M
and
x mod k = x
so that by letting
N mod k = N_k
and
( a + b ) mod k = a +_k b
you have
N_k +_k x = M
which means that what you need is the inverse of N_k under +_k. This is actually pretty simple because the inverse under +_k is whatever satisfies this equation:
N_k +_k ("-N_k") = 0
which is actually pretty simple because for a number y such that 0 <= y < k
(y + (k - y)) mod k = k mod k = 0
so that
"-N_k" = (k-N_k)
and then
N_k +_k x +_k "-N_k" = N_k +_k "-N_k" +_k x = 0 +_k x = x = M +_k "-N_k" = M +_k ( k - N_k )
so that the solution to
( N + x ) mod k = M
is
x = ( M + ( k - ( N mod k ) ) ) mod k
and for your problem in particular
( 12345600 + x ) % 97 = 1
is solved by
x = ( 1 + ( 97 - ( 12345600 mod 97 ) ) ) mod 97 = 76
Do notice that the requirement that you solution always have two digits is built in as long as k < 100

Resources