Convert specific parts of string to uppercase?

Viewed 187

I have a DataFrame and I'd like to make only specific parts of strings to be made uppercase with an underscore afterwords.

|         TYPE       |  NAME  |
|-----------------------------|
| Contract Employee  | John   |
| Full Time Employee | Carol  |
| Temporary Employee | Kyle   |

I'd like the words "Contract" and "Temporary" made into uppercase like this with an underscore after and before the word:

|         TYPE         |  NAME  |
|-------------------------------|
| _CONTRACT_ Employee  | John   |
| Full Time Employee   | Carol  |
| _TEMPORARY_ Employee | Kyle   |

I tried using str.upper() but that made the entire cell uppercase and I'm looking only for those certain words.

EDIT: I should mention sometimes the words are not capitalized if that matters. Often it will display as temporary employee instead of Temporary Employee.

5 Answers

Here is one option using re.sub:

def type_to_upper(match):
    return match.group(1).upper()

text = "Contract Employee"
output = re.sub(r'\b(Contract|Temporary)\b', type_to_upper, text)

EDIT:

This is the same approach applied within pandas, also addressing the latest edit regarding uncertain upper or lower case words to be replaced:

test dataframe:

                 TYPE   NAME
0   Contract Employee   John
1  Full Time Employee  Carol
2  Temporary Employee   Kyle
3   contract employee   John
4  Full Time employee  Carol
5  temporary employee   Kyle

solution:

def type_to_upper(match):
    return '_{}_'.format(match.group(1).upper())

df.TYPE = df.TYPE.str.replace(r'\b([Cc]ontract|[Tt]emporary)\b', type_to_upper)

result:

df 
                   TYPE   NAME
0   _CONTRACT_ Employee   John
1    Full Time Employee  Carol
2  _TEMPORARY_ Employee   Kyle
3   _CONTRACT_ employee   John
4    Full Time employee  Carol
5  _TEMPORARY_ employee   Kyle

Note that this is only for addressing exactly these two cases which are defined in the OPs request. For complete case insensitivity it's even simpler:

df.TYPE = df.TYPE.str.replace(r'\b(contract|temporary)\b', type_to_upper, case=False)

Something that modifies the data-frame (without regex or anything):

l=['Contract','Temporary']
df['TYPE']=df['TYPE'].apply(lambda x: ' '.join(['_'+i.upper()+'_' if i in l else i for i in x.split()]))

join and split, being in a apply.

And then now:

print(df)

Is:

                   TYPE   NAME
0   _CONTRACT_ Employee   John
1    Full Time Employee  Carol
2  _TEMPORARY_ Employee   Kyle

This is simples and easy way by using replace with dictionary format.

Please refer pandas Doc for Series.replace

df["TYPE"] = df["TYPE"].replace({'Contract': '_CONTRACT_', 'Temporary': '_Temporary_'}, regex=True)

Just reproduced:

>>> df
                 TYPE   Name
0   Contract Employee   John
1  Full Time Employee  Carol
2  Temporary Employee   Kyle

>>> df["TYPE"] = df["TYPE"].replace({'Contract': '_CONTRACT_', 'Temporary': '_TEMPORARY_'}, regex=True)
>>> df
                   TYPE   Name
0   _CONTRACT_ Employee   John
1    Full Time Employee  Carol
2  _TEMPORARY_ Employee   Kyle

U9 beat me to it, using lambda and split() on the input:

def match_and_upper(match):
    matches = ["Contract", "Temporary"]
    if match in matches:
        return match.upper()
    return match

input = "Contract Employee"
output = " ".join(map(lambda x: match_and_upper(x), input.split()))
# Result: CONTRACT Employee # 

Answering part of my own question here. Using @Tim Biegeleisen's regex he provided, I did a string replace on the column.

df["TYPE"] = df["TYPE"].str.replace(r'\b(Contract)\b', '_CONTRACT_')
Related