Can someone explain to me why only the first IF ELSE statement in my code works? I am trying to combine multiple variables into one.
DATA BCMasterSet2;
SET BCMasterSet;
drop PositiveLymphNodes1;
if PositiveLymphNodes1 = "." then PositiveLymphNodes =
put(PositiveLymphNodes2, 2.);
else PositiveLymphNodes = PositiveLymphNodes1;
if PositiveLymphNodes2 = "." then new_posLymph = put(PositiveLymphNodes,
2.);
else new_posLymph = PositiveLymphNodes2;
RUN;
Here is a nice screenshot of what the incorrect output looks like:OUTPUT
Thanks!
Hard to say without seeing all of your data, but I have a suspicion: is positivelymphnodes1 character or numeric? Is it ever actually equal to "."?
If you are trying to say "if PositiveLymphNodes1 is missing", then you can say that this way:
if missing(positivelymphnodes1) then ...
You can also do the same thing using coalesce or coalescec (the latter is character, the former numeric, in its return value). It chooses the first nonmissing argument. - so if the first argument is missing, it chooses the second.
positiveLymphNodes = coalescec(PositiveLymphNodes1, put(positiveLymphNodes2,2.));
new_posLymph = coalescec(positiveLymphNodes2, put(positiveLymphNodes,2.));
I would be curious why you're using put only in one place and not the other - use it in both or neither, I would suggest.
Related
I am using Stata 14. I have US states and corresponding regions as integer.
I want create a string variable that represents the region for each observation.
Currently my code is
gen div_name = "A"
replace div_name = "New England" if div_no == 1
replace div_name = "Middle Atlantic" if div_no == 2
.
.
replace div_name = "Pacific" if div_no == 9
..so it is a really long code.
I was wondering if there is a shorter way to do this where I can automate assigning values rather than manually hard coding them.
You can define value labels in one line with label define and then use decode to create the string variable. See the help for those commands.
If the correspondence was defined in a separate dataset you could use merge. See e.g. this FAQ
There can't be a short-cut here other than typing all the names at some point or exploiting the fact that someone else typed them earlier into a file.
With nine or so labels, typing them yourself is quickest.
Note that you type one statement more than you need, even doing it the long way, as you could start
gen div_name = "New England" if div_no == 1
I can't figure out why this if statement won't work.
I have a DateTime field DATEFROM and a String parameter (it HAS to be String) periodEnd.
I would like to calculate percentages depending if these two dates have 1, 2, 3 or more years difference.
When I use this formula I get either "100%" or "-" and never the other two options. It's like CR calculates the first IF and if it's true then: "100%" but if it's false, it never checks for the rest of the Else Ifs and goes dirreclty to Else
StringVar percentage:="";
If (cDate({?periodEnd})-{TABLE.DATEFROM})<=1 Then
percentage:="100%"
Else If (cDate({?periodEnd})-{TABLE.DATEFROM})<=2 Then
percentage:="66%"
Else If (cDate({?periodEnd})-{TABLE.DATEFROM})<=3 Then
percentage:="33%"
Else
percentage:="-"
Any idea?
a) I assume you already made sure your periodend format matches with what cdate interprets?
If you just subtract them, Crystal by default returns the number of days between.
Two ways you can do year:
datediff("yyyy",cDate({?periodEnd},{TABLE.DATEFROM})
or
year(cDate({?periodEnd})-year({TABLE.DATEFROM})
b) You've also no doubt accounted for when your {TABLE.DATEFROM} is greater than cDate({?periodEnd} and you have a negative result?
Not sure if the following is the behavior you would want, but I'm throwing it in for your information
ABS(datediff("yyyy",cDate({?periodEnd},{TABLE.DATEFROM}))
**make sure you check the help file for the datediff codes ("yyyy" etc) as they are not quite instinctive and can trip you up when you think you're using the obvious one
It looks like a simple task, but how would you solve it? I don't get any solution right now.
ls_message-text = 'Pernr. 12345678 (Pete Peterson) is valid (06/2015).
append ls_message to lt_message.
ls_message-text = 'Pernr. 12345678 (Pete Peterson) is valid (07/2015).
append ls_message to lt_message.
This is the code I got, the thing is, this is the message I am showing in my application. The customer says that the 2 messages are the same. The second should be deleted.
How would you compare it to delete the line? The table might contain more then 2 lines and also with another text like "is not valid".
I can't extend the structure to have more fields for comparison, I can only use the string comparison on this one field. Are there string comparisons possible with a regex or something?
Maybe you could solve your requirement using the Levenshtein distance . ABAP has a built-in function "distance" that gives you the number of operations to convert one string into another. Ex:
DATA msg1 type string.
DATA msg2 type string.
msg1 = 'Levehnstein Distance 7/2015'.
msg2 = 'Levehnstein Distance 6/2015'.
data l_distance type i.
l_distance = distance( val1 = msg1 val2 = msg2 ).
if l_distance lt 2 .
"It's almost the same text
endif.
In this case l_distance will be 1, because only one operation is necessary (replacing).
Hope this helps,
Assuming you want to retain only one message for each unique Pernr. in lt_message, you can use regex to filter for the Pernr. and use that as "key". Now you can delete all but the first message of lt_message that matches this key.
Expand your regex if you want to keep only certain messages, e.g. only the "is valid" ones.
have you tried looking to program DEMO_REGEX_TOY.
Gives an idea on how to work with Regular expresion, that probably will save the problem
I want to write a formula that looks at the value of a specific cell across other sheets and returns the last non-empty value.
For example, if:
Sheet2.B5 = 3
Sheet3.B5 = ""
Sheet4.B5 = 6
Sheet5.B5 = 4
Sheet6.B5 = ""
Then I would want the formula to return 4.
Any help is much appreciated, I've been working on this for a while without success.
This returns the desired result, although it's not sophisticated or automatic in any way:
=if(not(isblank(Sheet6.B5)), Sheet6.B5,
if(not(isblank(Sheet5.B5)), Sheet5.B5,
if(not(isblank(Sheet4.B5)), Sheet4.B5,
if(not(isblank(Sheet3.B5)), Sheet3.B5,
if(not(isblank(Sheet2.B5)), Sheet2.B5,
"")))))
It starts looking at the last Sheet6.B5: if it's not blank, that's the value to take, otherwise look at Sheet5.B5: if it's not blank... and so on. Finally if they are all blank, return blank.
Given the following table:
Table: Comedians
=================
Id First Middle Last
--- ------- -------- -------
1 Bob NULL Sagat
2 Jerry Kal Seinfeld
I want to make the following prepared query:
SELECT * FROM Comedians WHERE Middle=?
work for all cases. It currently does not work for the case where I pass NULL via sqlite3_bind_null. I realize that the query to actually search for NULL values uses IS NULL, but that would mean that I cannot use the prepared query for all cases. I would actually have to change the query depending on the input, which largely defeats the purpose of the prepared query. How do I do this? Thanks!
You can use the IS operator instead of =.
SELECT * FROM Comedians WHERE Middle IS ?
Nothing matches = NULL. The only way to check that is with IS NULL.
You can do a variety of things, but the straight forward one is...
WHERE
middle = ?
OR (middle IS NULL and ? IS NULL)
If there is a value you know NEVER appears, you can change that to...
WHERE
COALESCE(middle, '-') = COALESCE(?, '-')
But you need a value that literally NEVER appears. Also, it obfuscates the use of indexes, but the OR version can often suck as well (I don't know how well SQLite treats it).
All things equal, I recommend the first version.
NULL is not a value, but an attribute of a field. Instead use
SELECT * FROM Comedians WHERE Middle IS NULL
If you want match everything on NULL
SELECT * FROM Comedians WHERE Middle=IfNull(?, Middle)
if want match none on NULL
SELECT * FROM Comedians WHERE Middle=IfNull(?, 'DUMMY'+Middle)
See this answer: https://stackoverflow.com/a/799406/30225