Change text case

toupper() / tolower() / toTitleCase()

SAS: UPCASE, LOWCASE, PROPCASE

toupper() and tolower() match UPCASE and LOWCASE on ASCII letters A-Z and a-z. Digits and symbols are unchanged in both languages. Base R has no PROPCASE. The house stand-in for plain words is tools::toTitleCase(tolower(x)). It is not the same function.

Quick reference

toupper(x)                         # UPCASE
tolower(x)                         # LOWCASE
tools::toTitleCase(tolower(x))     # stand-in for PROPCASE; not equal to it
R SAS
toupper(x) UPCASE(x)
tolower(x) LOWCASE(x)
tools::toTitleCase(tolower(x)) PROPCASE(x) for plain words only

Traps: tools::toTitleCase() is not PROPCASE. PROPCASE capitalizes every word, including of. toTitleCase() leaves English function words lowercase, and it does not treat . as a word break (N.C. becomes N.c. after tolower()). An all-caps word is left unchanged unless you tolower() first. toupper() on a factor returns character, not a factor. toupper(NA) is NA. "" stays "".

Worked examples below.

USUBJID and ARM

library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
ae <- data.frame(
  USUBJID = c("std-001-0001", "STD-001-0002"),
  ARM = c("Placebo", "Active"),
  AETERM = c("HEADACHE OF MILD SEVERITY", "Nausea")
)

ae |>
  mutate(
    USUBJID = toupper(USUBJID),
    ARM_UP = toupper(ARM),
    ARM_LO = tolower(ARM)
  )
       USUBJID     ARM                    AETERM  ARM_UP  ARM_LO
1 STD-001-0001 Placebo HEADACHE OF MILD SEVERITY PLACEBO placebo
2 STD-001-0002  Active                    Nausea  ACTIVE  active

SAS:

usubjid = upcase(usubjid);
arm_up = upcase(arm);
arm_lo = lowcase(arm);

toupper() changes std-001-0001 to STD-001-0001. Hyphens and digits stay. ARM_UP is PLACEBO and ACTIVE. ARM_LO is placebo and active.

Proper case

PROPCASE lowercases the argument, then capitalizes the first character of each word. The default word breaks are blank, /, -, (, ., and tab. SAS documents PROPCASE("INTRODUCTION TO THE SCIENCE OF ASTRONOMY") as Introduction To The Science Of Astronomy. Words such as To and Of are capitalized.

ae |>
  mutate(AETERM_TC = tools::toTitleCase(tolower(AETERM)))
       USUBJID     ARM                    AETERM                 AETERM_TC
1 std-001-0001 Placebo HEADACHE OF MILD SEVERITY Headache of Mild Severity
2 STD-001-0002  Active                    Nausea                    Nausea

tools::toTitleCase(tolower(AETERM)) returns Headache of Mild Severity and Nausea. of stays lowercase. PROPCASE("HEADACHE OF MILD SEVERITY") returns Headache Of Mild Severity.

tolower() first is required. toTitleCase() leaves an all-caps word unchanged:

tools::toTitleCase("HEADACHE")
[1] "HEADACHE"
tools::toTitleCase(tolower("HEADACHE"))
[1] "Headache"

HEADACHE, then Headache. SAS propcase("HEADACHE") is Headache.

. is a PROPCASE word break and is not a toTitleCase() word break. SAS documents PROPCASE("WINSTON-SALEM, N.C.") as Winston-Salem, N.C..

tools::toTitleCase(tolower("WINSTON-SALEM, N.C."))
[1] "Winston-Salem, N.c."

N.C. becomes N.c..

ImportanttoTitleCase() is not PROPCASE

PROPCASE capitalizes every word and splits on .. tools::toTitleCase() leaves English function words (of, the, to, and others) lowercase unless they lead the string, and it does not split on .. Call tolower() first or an all-caps word is returned unchanged.

Factors

arm <- factor(c("Placebo", "Active"))
toupper(arm)
[1] "PLACEBO" "ACTIVE" 
class(toupper(arm))
[1] "character"

The result is character, the uppercased labels, not a factor. SAS character values are not factors. Wrap factor() again if a later step requires one.

toupper(NA) is NA. toupper("") is "". SAS UPCASE of a blank stays blank.

UPCASE, LOWCASE, and PROPCASE follow the SAS locale and translation table. The examples on this page are ASCII A-Z. toupper() and tolower() follow the R locale for letters outside that range.