multiple conditions on multiple variables - sas

would really love to get some help on a sas program i am trying to write
I have five variables that have the options Interest or Rewards
call them wo1 wo2 wo3 wo4 wo5
is there a way to do an if statement that checks all five for the value of "Interest" and then produces a calcualted variable with the totals of the variable that holds the amount value which are wo1amt wo2amt wo3mt etc.
and the ones that do not have the value of interest return a value of 0.
or would i need to do an if statement for each, creating a calc var for each and then summing them all together with another ??
any assistance, direction would be very appreciated...

If I'm understanding correctly, it looks like you will need multiple if statements.
You could initialize a total variable, and then add to it for each contributing variable, like this:
total = 0;
if wo1 = 'Interest' then total = total + wo1amt;
if wo2 = 'Interest' then total = total + wo2amt;
if wo3 = 'Interest' then total = total + wo3amt;
if wo4 = 'Interest' then total = total + wo4amt;
if wo5 = 'Interest' then total = total + wo5amt;

Arrays work nicely for situations like this.
array wo(*) wo1-wo5;
array woamt(*) wo1amt wo2amt wo3amt wo4amt wo5amt;
total = 0;
do i = 1 to 5;
total + woamt(i)*(wo(i)='Interest');
end;

Related

How to generate item variables from total score variable

I want to simulate the item score from total score.
For example, I have generated the total score, which has scores between 5 and 25. I would like to distribute this total score to five items with each having a 5-Likert score.
Then I used a while loop to check the condition in Stata 15. The code takes took too long to finish looping and I do not know whether I have made a mistake.
Perhaps someone would like to suggest another way to simulate the item score from the total score?
My code:
set obs 200
generate id=_n
generate u_i= rnormal(0, 0.5)
generate gr = runiform()>0.5
generate sex = runiform()>0.4
generate age = round(rnormal(65, 10))
expand 5
bysort id: generate time=_n
generate e_ij = rnormal(0, 1.0)
generate run=_n
*Generate Sum score 5-25
generate y = 3.0 + 2.0*gr + 0.2*age -1.2*sex + 0.5*time + u_i + e_ij
summarize y
replace y = round(y)
*Generate each item
forvalues k = 1(1)5 {
generate item`k' = runiform(1, 5)
replace item`k' = round(item`k')
}
egen sum_item=rowtotal(item1 item2 item3 item4 item5)
generate diff = y - sum_item
*Looping check if y=sum_item
forvalues a = 1(1)`=_N' {
quietly gsort -diff
while sum_item!=y[`a'] {
replace sum_item=. if sum_item!=y[_n]
forvalues k = 1(1)5 {
replace item`k' =. if sum_item==.
replace item`k' = runiform(1, 5) if item`k'==.
replace item`k' = round(item`k')
}
replace sum_item= item1 + item2+item3+item4+item5 if sum_item==.
replace diff = y - sum_item
if (sum_item==y[`a']) continue, break
}
}
The expected data that I would like to have:
As you can see, after running the loop I will always get 2-4 cases that the program keep running by generating item score (item1-item5) until the diff variable equals zero.
If I'm understanding correctly, you could loop something like the following (after setting all the items to initial values of 1, since possible values are 1 to 5):
capture generate rand_int = 0
replace rand_int = floor( 5 * runiform() + 1 ) // random int, 1 to 5
capture generate cnd = 0
forvalues k = 1(1)5 {
replace cnd = rand_int == `k' & sum_item < y & item`k' < 6
replace item`k' = item`k' + 1 if cnd
}
replace sum_item = item1+item2+item3+item4+item5
In words, that says is that if sum_item < y, then randomly add 1 to one of the items (as long as that item is not already equal to 5), and then you would keep doing it until sum_item == y for all rows.
So that's going to converge in roughly 20 iterations if the max value of y is 25 and items are from 1 to 5. I say "roughly" because there is a little waste in here when you add 1 to an item that is already equal to 5. You could ad some extra code for that, but I wouldn't bother if this is fast enough. E.g. for high values of item_sum it would be more efficient to start with initial values of 5 and randomly subtract 1 until it converges.
I'm not enough of a statistician to say that's the best or even an adequate way to do it, but intuitively to me it seems OK if you want a fairly uniform distribution of values. If you wanted the modal value to be 4, for example, that's a lot harder and not really a programming question any longer.

How to use fold statement index in function call

The fold manual gives an example:
input price = close;
input length = 9;
plot SMA = (fold n = 0 to length with s do s + getValue(price, n, length - 1)) / lenth;
This effectively calls a function iteratively like in a for loop body.
When I use this statement to call my own function as follows, then it breaks because the loop index variable is not recognized as a variable that can be passed to my function:
script getItem{
input index = 0;
plot output = index * index;
}
script test{
def total = fold index = 0 to 10 with accumulator = 0 do
accumulator + getItem(index);########## Error: No such variable: index
}
It is a known bug / limitation. Has been acknowledged without a time line for a fix. No workaround available.
Have you tried adding a small remainder to your defined variable within the fold and then pass that variable? You can strip the integer value and then use the remainder as your counter value. I've been playing around with somethin similar but it isn't working (yet). Here's an example:
script TailOverlap{
input i = 0;
def ii = (Round(i, 1) - i) * 1000;
... more stuff
plot result = result;
};
def _S = (
fold i = displace to period
with c = 0
do if
TailOverlap(i = _S) #send cur val of _S to script
then _S[1] + 1.0001 #increment variable and counter
else _S[1] + 0.0001 #increment the counter only
);
I'm going to continue playing around with this. If I get it to work I'll post the final solution. If you're able to get work this (or have discovered another solution) please do post it here so I know.
Thanks!

Python / print and assign random number every time

I'm trying to generate a random integral and assign it to the variable.
import random
import time
Op = lambda: random.randint(1300, 19000)
op = "https://duckduckgo.com/html?q="
variable = int(Op())
grow = 0
while x < 3:
print(Op())
grow = grow + 1
time.sleep(1)
In here everything works fine, function "print" prints different result every time with 3 attempts.
However when I want to format this code like this:
Op = lambda: random.randint(1300, 19000)
op = "https://duckduckgo.com/html?q="
Op1 = int(Op())
pop = str("{}{}").format(op, Op1)
grow = 0
while grow < 3:
print(pop)
grow = grow + 1
time.sleep(1)
Then the function print gives me the same number three times.
For example:
>>>https://duckduckgo.com/html?q=44543
>>>https://duckduckgo.com/html?q=44543
>>>https://duckduckgo.com/html?q=44543
And I would like to get three random numbers. For example:
>>>https://duckduckgo.com/html?q=44325
>>>https://duckduckgo.com/html?q=57323
>>>https://duckduckgo.com/html?q=35691
I was trying to use %s - %d formatting but the result is the same.
Because you never changes the value of 'pop'.
In you first example you are creating instance of Op in every iteration but in second example you created instance once outside the loop and print the same value.
Try this:
Op = lambda: random.randint(1300, 19000)
op = "https://duckduckgo.com/html?q="
grow = 0
while grow < 3:
pop = str("{}{}").format(op, int(Op()))
print(pop)
grow = grow + 1
time.sleep(1)
Lambda functions are by definition anonymous. If you need to "remember" a lambda's procedure, just use def statement. But actually you don't even need this:
import random
import time
url_base = "https://duckduckgo.com/html?q={}"
grow = 0
while grow < 3:
print(url_base.format(random.randint(1300, 19000))
grow = grow + 1
time.sleep(1)
Your main problem is that you are trying to assign fixed values to variables and expect them to behave like procedures.
You need to apply randomness at every iteration. Instead you calculate a random number once and plug it in to every loop.

Results of for loop not adding to variable

So i made the following code to calculate my overal adverage mark:
def report_card(GPA):
total = 0
for courses, marks in GPA:
print courses,'-',marks
for courses, marks in GPA:
total = total =+ marks
print total / len(GPA)
report_card([('History', 84), ('Physics', 76), ('English', 91), ('Science', 64)])
I thouht since I want total to be total += marks it would count count up all the marks of the subject i follow up together, but this is not happening, it prints the marks one-by-one and divide this one mark by 4 (the length of GPA)
So how do i make my marks be counted up as one number
The syntax is either:
total = total + marks
or:
total += marks
What you wrote is parsed as if you'd written:
total = total = (+marks)
+marks is equivalent to just marks, so it's equivalent to:
total = total = marks
which is equivalent to:
total = marks

Operations with structures, code not working?

Assume you are given three variables, revenue, expenses, and profit, all of type Money (a structured type with two int fields, dollars and cents). Assign to profit the result of subtracting expenses from revenue. Let's make the happy assumption that revenue exceeds expenses. However you still may find that the cents part of expenses exceeds that of revenue. If that is the case you will have to "borrow" 1 from revenue dollars (i.e. subtract 1) and "give" it to revenue's cents (i.e. add 100!) in order to carry out the subtraction properly.
Here is what I have but it's not working:
if (revenue.cents < expenses.cents)
{
revenue.dollars = revenue.dollars -1;
revenue.cents = revenue.cents + 100;
profit = revenue - expenses;
}
else
{
profit = revenue - expenses;
}
I get this error message:
error: no match for 'operator-' in 'revenue - expenses'
Any help is appreciated. Thanks.
You're getting that error because you cannot subtract one structure from another. You will have to define an operator-() function for your struct.
You need to call each element of the structure and subtract them separately. MyProgLab will not allow you to define a function for this exercise. Not only that but if you enter the code that you have above it will tell you that 'you were not supposed to modify the element'. In order to avoid this you must conduct the borrowing of the dollar inside the arithmetic.
Like this:
if(expenses.cents > revenue.cents)
{
profit.dollars = (revenue.dollars - 1) - expenses.dollars;
profit.cents = (revenue.cents + 100) - expenses.cents;
}//end if