name prefix and suffix removal SAS - sas

I am looking for a way to remove a list of prefix and suffixes from the name variable
For example
under name I have
Mr. Walter White Jr.
I wish to keep just Walter White
I have list of prefixes and suffixes that I can use a reference
thanks in advance

Use regular expressions with your list to replace them with blank values.
data have;
infile datalines dlm='|';
length name $20.;
input name$;
datalines;
Mr. Walter White Jr.
Mrs. Skyler White
Dr. Saul Goodman
Mr. Jesse Pinkman
Mr. Gus Fring
;
run;
data want;
set have;
name = strip(prxchange('s/(Mr.|Jr|Dr)\.?//', -1, name) );
run;
Output:
name
Walter White
Skyler White
Saul Goodman
Jesse Pinkman
Gus Fring

Related

Why does my regex only change my first entry in SAS?

I have a number of text entries (municipalities) from which I need to remove the s at the end.
Data test;
input city $;
datalines;
arjepogs
askers
Londons
;
run;
data cities;
set test;
if prxmatch("/^(.*?)s$/",city)
then city=prxchange("s/^(.*?)s$/$1/",-1,city);
run;
Strangely enough, my s's are only removed from my first entry.
What am I doing wrong?
You defined CITY as length $8. The s in Londons is in the 7th position of the string. Not the LAST position of the string. Use the TRIM() function to remove the trailing spaces from the value of the variable.
data have;
input city $20.;
datalines;
arjepogs
Kent
askers
Londons
;
data want;
set have;
length new_city $20 ;
new_city=prxchange("s/^(.*?)s$/$1/",-1,trim(city));
run;
Result
Obs city new_city
1 arjepogs arjepog
2 Kent Kent
3 askers asker
4 Londons London
You could also just change the REGEX to account for the trailing spaces.
new_city=prxchange("s/^(.*?)s\ *$/$1/",-1,city);
Here is another solution using only SAS string functions and no regex. Note that in this case there is no need to trim the variable:
data cities;
set test;
if substr(city,length(city)) eq "s" then
city=substr(city,1,length(city)-1);
run;

Splitting a cell up using delimiters, but the delimiter is before the desired split location

I have some data in the form of a column in a dataset (named Person_details), where each has an unknown number of names, with the name (split up by spaces), followed by an underscore, followed by that persons identifier (7 characters).
Is there a way to split these entries up automatically, rather than repeatedly finding the position of the underscore, and then taking the substring before and after?
Person_details:
Evan Davies_123F323 Adam John Smith_342D427 Karl Marx_903C943
There are an unknown number of names in each cell, e.g. some have just one name and some have 20. Also complicated by the fact that some entries have middle name(s).
The ideal output would be in the form
Name Code
Evan Davies 123F323
Adam John Smith 342D427
Karl Marx 903C943
You could just use SCAN() instead.
data have;
string='Evan Davies_123F323 Adam Smith_342D427 Karl Marx_903C943';
length name $50 code $7 ;
do index=1 to countw(string,' ');
name = catx(' ',name,scan(string,index,' '));
if index(name,'_') then do;
code = scan(name,-1,'_');
name = substr(name,1,length(name)-length(code)-1);
output;
name=' ';
end;
end;
run;
Result
You can use a Perl regular expression (regex) to detect and extract pieces from patterned text. SAS routine PRXNEXT iterates through matches, and function PRXPOSN extracts pieces.
Example:
data have;
text = 'Evan Davies_123F323 Adam John Smith_342D427 Karl Marx_903C943';
run;
data want(keep=name code);
rx = prxparse('/(.+?)_(.{7}( |$))/');
set have;
start = 1;
stop = length(text);
do seq = 1 by 1;
call prxnext(rx,start,stop,text,position,length);
if position=0 then leave;
name = prxposn(rx,1,text);
code = prxposn(rx,2,text);
output;
end;
run;

Remove values from a string SAS

I have this column which i would wish to remain only the names and wish to remove everything after the ( s. May i know how could i achieve this?
Name Age
James 12
John (funny) 11
Jonathan 10
Alisa (134 cm) 12
Merlin (cheerful) 12
Jessica (hopeful) 12
Ali (quiet) 13
I have tried using functions such as compress but it still didnt work
data output;
length Name $30.;
infile datalines dlm=',';
input Name$ Age;
new = compress(name, '()');
datalines;
James,12
John (funny),11
Jonathan,10
Alisa (134 cm),12
Merlin (cheerful),12
Jessica (hopeful),12
Ali (quiet),13
;
Updating based on Tom's suggestion:
Use scan() and treat ( as a delimiter. This will pull all text before the first (.
new = scan(name, 1, '(', 'T')
The T option trims any trailing blanks.
You can use Perl regular expression patterns to replace parenthetical content with 'nothing'
name = prxchange ('s/\(.*?\)//', -1, name);

Remove Middle Initial but not Middle Name from string

I'm trying to find a way to remove the Middle initial from a string containing the First name and middle initial (example "Mary A" needs to be "Mary").
However, I would need to keep the middle/second name if it was more than an initial (example "Mary Ann" would stay "Mary Ann").
Much thanks,
Matt
Try to use the function scan:
data test;
input name $20.;
cards;
Mary A
Anthony B
Mary Ann
Anthony Bernard
;
run;
data res;
set test;
if (length(scan(name,2))=1) then name=scan(name,1);
run;
As a result, you get:
Mary
Anthony
Mary Ann
Anthony Bernard
Here's an example of how to do this using regular expression substitution. I've used proc sql but this would also work in a data step:
data names;
input name & $5.;
cards;
Aa A
Aa Aa
Aaa A
;
run;
proc sql;
select prxchange('s/^(\w+)\s+\w\s*$/$1/',-1,name) from names;
quit;
The regex is built up as follows:
Capture the first word
Match a space, a single character, then any number of trailing spaces
If the whole expression is a match, return only the first word, otherwise return the whole input string unchanged.

Character value with embedded blanks with list input

I would like to read following instream datalines
datalines;
Smith,12,22,46,Green Hornets,AAA
FriedmanLi,23,19,25,High Volts,AAA
Jones,09,17,54,Las Vegas,AA
;
I employed while it read AAA items to team variables but not as div. And how should I place &(ampersand to read character with embedded blanks?)
data scores2;
infile datalines dlm=",";
input name : $10. score1-score3 team $20. div $;
datalines;
Smith,12,22,46,Green Hornets,AAA
FriedmanLi,23,19,25,High Volts,AAA
Jones,09,17,54,Las Vegas,AA
;
run;
Notice I have used : before team also ( well you have already used colon operator : for other variables , not sure why did you miss over here) As I have already mentioned in your other query, use : colon operator (tilde, dlm and colon format modifier in list input) which would tell SAS to use the informat supplied but to stop reading the value for this variable when a delimiter is encountered. Here as you had not used this operator , that is why SAS was trying to read 20 chars, even though
there was a delimiter in between.
Tested
data scores2;
infile datalines dlm=",";
input name : $10.
score1-score3
team : $20.
div : $3.;
datalines;
Smith,12,22,46,Green Hornets,AAA
FriedmanLi,23,19,25,High Volts,AAA
Jones,09,17,54,Las Vegas,AA
;
run;
Another way to do this that's often a bit easier to read is to use the informat statement.
data scores2;
infile datalines dlm=",";
informat name $10.
team $20.
div $4.;
input name $ score1-score3 team $ div $;
datalines;
Smith,12,22,46,Green Hornets,AAA
FriedmanLi,23,19,25,High Volts,AAA
Jones,09,17,54,Las Vegas,AA
;
run;
That accomplishes the same thing as using the colon (input name :$10.) but organizes it a bit more cleanly.
And just to be clear, embedded blanks are irrelevant in comma delimited input; '20'x (ie, space) is just another character when it's not the delimiter. What ampersand will do is addressed in this article, and more specifically, if space is the delmiiter it allows you to require two consecutive delimiters to end a field. Example:
data scores2;
infile datalines dlm=" ";
informat name $10.
team $20.
div $4.;
input name $ score1-score3 team & $ div $;
datalines;
Smith 12 22 46 Green Hornets AAA
FriedmanLi 23 19 25 High Volts AAA
Jones 09 17 54 Las Vegas AA
;
run;
Note the double space after all of the team names - that's required by the &. But this is only because delimiter is space (which is default, so if you removed the dlm=' ' it would also be needed.)