Skip to contents

Converts a character (text) or factor variable into numeric codes, attaching the original words as value labels so every later table still shows the words. With no map, codes are assigned alphabetically (a factor's levels keep their own order) and the assignment is printed; with a map, you choose the numbers. Numbers stored as text ("34") always convert to their own value, never to a rank.

Usage

jencode(data, var, map = NULL, labels = NULL, convention = NULL, ...)

Arguments

data

A data frame containing the variable to encode. Can be omitted if a default data frame has been set with juse().

var

The text or factor variable to encode (unquoted name; a quoted name is accepted). Character variables and factors are accepted; numeric, logical, and date/time variables are refused with a message naming the right tool (for numeric variables, that is jrecode()).

map

Optional. A single string of semicolon-separated rules, each word=number: for example "Bail=1; Parole=2; Remand=3". Matching against the data is case-sensitive, after outer spaces are trimmed on both sides (a note reports any cells that matched only after trimming). Words containing a semicolon must be double-quoted ('"Not applicable; other"=3'); apostrophes need no quoting: map = "Yes=1; Don't know=8" works as typed.

Special left-hand sides: blank=<number> gives empty cells their own code. With no map, blanks are left missing and a note shows the blank rule to use; with a map, blanks count as unmapped, so a map that neither names them nor carries an else rule stops with the same incomplete-map error. Special targets: else=NA converts every unmapped word to system missing; else=.a (through .z) converts them to a tagged missing value under the Stata or SAS convention (see convention). else=copy is refused: words cannot be kept in a numeric column. A word may also be sent to the word missing – your working convention's own missing form, declared automatically under the SPSS convention (see jrecode()'s map for the full rule); blank=missing composes the two keywords. Under the SPSS convention the code the keyword uses must be free: if the map also assigns it as an ordinary value, or a number stored as text is kept at that same value, the call stops rather than sweep those cases into missingness. Under the Stata or SAS convention the keyword always uses the first marker (.a, or .A), so a map that also assigns that marker itself stops rather than merge two missing categories onto one marker.

By default an incomplete map is an error that names the unmatched words (nothing is dropped silently); add an else rule to sweep the remainder deliberately, and the note then names the words it swept.

labels

Optional. A single string of semicolon-separated number=Label pairs overriding the automatic labels: for example "1=Low; 2=Medium; 3=High". If omitted, each word becomes the label of its own code. When several words collapse to one code, no label can be chosen automatically and a note directs you here or to jrelabel(). A label may be written in quotes, with either mark, right after its equals sign, and a semicolon inside the quotes is then part of the label: "1=Yes; 9=\"Refused; not asked\"". An unquoted label reads as it is written.

convention

Optional. One of "spss", "stata", "sas", or NULL (default); any capitalization is accepted. Controls whether missing-value markers (.a through .z or .A through .Z) are accepted as map targets. Marker letters are matched case-insensitively; the stored markers take the convention's letter case (lowercase Stata-style under "stata", uppercase SAS-style under "sas"). Also decides what the missing keyword produces. Inert when neither a marker nor missing appears in the map.

...

Not used. An input jencode() does not take – a misspelled argument – stops with "unused input" and the name as typed, in place of R's own "unused argument".

When NULL, the convention is resolved from the missing.convention setting in joptions; if that is also unset, the call stops with a guided error asking you to choose – the package never infers a convention. Most users set the convention once at the top of a session via joptions() (or in their .Rprofile) rather than supplying this argument on every call. See ?joptions for details.

Value

A haven_labelled numeric vector with the encoded values and (unless overridden) the original words as value labels. The function returns the values rather than changing data: assign the result to a column to keep it. Two assignment forms do that job:

  • Preserving (recommended): MyData$StatusR <- jencode(MyData, Status) adds a new column and keeps the original text, so the two can be compared with jfreq() before the text is retired.

  • Overwrite: MyData$Status <- jencode(MyData, Status) replaces the text in place. Nothing is wrong with this once the encoding is verified, but the original words in the data are gone.

SPSS users will recognize the pair: RECODE ... INTO new. is the preserving form and bare RECODE the overwrite, and SPSS's own text-to-numbers command (AUTORECODE, below) offers only the preserving form.

Details

The SPSS parallel. AUTORECODE is the SPSS command for this job. Given a text variable it assigns consecutive numbers to the distinct values in alphabetical order, stores the original text as value labels, and writes the result to a new variable. Before:

Status:  "Parole"  "Bail"  "Remand"  "Bail"

After AUTORECODE VARIABLES=Status /INTO StatusR.:

StatusR: 2  1  3  1
with value labels  1 "Bail"  2 "Parole"  3 "Remand"

jencode()'s automatic mode does exactly this, and additionally prints the assignment listing plus a ready-made map call so an ordered set (Low / Medium / High) can be renumbered deliberately rather than accepted alphabetically.

A factor is text with a declared order. R's factor() stores categories as level text in a set order, so jencode() accepts a factor as it accepts a text variable, with two differences that honor the declaration: the codes follow the level order rather than the alphabet (the same thing for a factor built without levels =, whose levels are alphabetical), and a level with no cases keeps its code and label, tagged (no cases) in the listing. An ordered factor (ordered = TRUE) has already declared its order, so the rerun-with-a-map suggestion is not printed for it. Levels that are all numbers convert by face value, like numbers stored as text. With a map, the rules name the level text exactly as they name words. This is also the route from a factor to jrecode() and jrelabel(), which work on numeric variables only, and to jdeclare_missing(), which takes numeric and text variables but not a factor.

Numbers stored as text convert by face value. Here the two part company. AUTORECODE treats "34" as just another string and renumbers it to its alphabetical rank; jencode() always converts a number stored as text to its own value ("34" becomes 34, never 2), because a column of ages that arrives as text should leave as ages. When every cell is numeric text, no value labels are attached and a note says so.

Repair mode. A map containing only an else rule – map = "else=NA" – is the one-line repair for a poisoned column (numbers plus stray word codes plus blanks, the shape a spreadsheet import often produces): the numbers are kept at face value and every word and blank is swept to missing. When a kept value looks like a coded missing value – by magnitude, or because a swept word such as "Refused" is evidence the column carried missing-value codes – a note suggests declaring it with jdeclare_missing() rather than losing it.

Blanks are counted separately. An empty cell ("") is neither a word nor an NA. In automatic mode blanks are left missing, with a note showing the blank= rule; with a map they must be named or swept by an else rule, and mapping blank=0 (or any code) gives them their own category, which matters in field data where a blank often means "No". Every map a note offers after an automatic call names the blank cells (and any declared missing strings, below), so each offered call runs as printed.

A map word the data do not hold. A map may name a word no case holds, to label a category ahead of time; a note says so at the full output level. When an else rule sent a word of the data to missing in the same call, the note is shown at every level, under the note naming the swept word: together the two usually mean a mistyped map word ("Parol=2; else=NA" sends every "Parole" to missing).

Declared missing values on a text variable. A file from SPSS can declare some of a string variable's values missing (MISSING VALUES MARITAL ('UNKNOWN')). In automatic mode those cells are left missing rather than numbered as categories, and a note gives the map that keeps them declared (UNKNOWN=missing). The word missing produces one missing value, so two declared strings sent to it share it; to keep them apart, give each a number of its own in the map and declare those numbers with jdeclare_missing. With a map they are words like any other: name them, or the call stops and lists them.

The variable label from the original variable is carried across automatically with "(encoded)" appended; if there is none, the variable name is used instead.

See also

jrecode for changing numeric values, jrelabel for value labels, jdeclare_missing for declaring missing-value codes, jfreq for checking an encoding landed correctly.

Examples

MyData <- data.frame(
  Status = c("Parole", "Bail", "Remand", "Bail"),
  Answer = c("Yes", "No", "Don't know", ""),
  AgeTxt = c("34", "41", "-99", "Refused"),
  stringsAsFactors = FALSE
)

# Automatic mode: alphabetical, listing printed, words become labels
MyData$StatusR <- jencode(MyData, Status)
#> Note: 'Status' was encoded alphabetically:
#>   "Bail"   -> 1
#>   "Parole" -> 2
#>   "Remand" -> 3
#> If these categories have a natural order (like Low/Medium/High), rerun with a
#> map to choose the numbers:
#>   MyData$StatusR <- jencode(MyData, Status, map = "Bail=1; Parole=2; Remand=3")
#> 
#> Note: This call changes MyData only if you assign the result:
#>   MyData$<name> <- jencode(...)
#> To check the encoding landed correctly, compare jfreq() on the original and the
#> new column.

# The data frame may also be given by name, or set once with juse()
MyData$StatusR <- jencode(data = MyData, Status)
#> Note: 'Status' was encoded alphabetically:
#>   "Bail"   -> 1
#>   "Parole" -> 2
#>   "Remand" -> 3
#> If these categories have a natural order (like Low/Medium/High), rerun with a
#> map to choose the numbers:
#>   MyData$StatusR <- jencode(MyData, Status, map = "Bail=1; Parole=2; Remand=3")
#> 
#> Note: This call changes MyData only if you assign the result:
#>   MyData$<name> <- jencode(...)
#> To check the encoding landed correctly, compare jfreq() on the original and the
#> new column.
juse(MyData)
#> Default data frame set to: MyData
MyData$StatusR <- jencode(Status)
#> Note: 'Status' was encoded alphabetically:
#>   "Bail"   -> 1
#>   "Parole" -> 2
#>   "Remand" -> 3
#> If these categories have a natural order (like Low/Medium/High), rerun with a
#> map to choose the numbers:
#>   MyData$StatusR <- jencode(MyData, Status, map = "Bail=1; Parole=2; Remand=3")
#> 
#> Note: This call changes MyData only if you assign the result:
#>   MyData$<name> <- jencode(...)
#> To check the encoding landed correctly, compare jfreq() on the original and the
#> new column.
juse(NULL)
#> Default data frame cleared.

# Map mode: choose the numbers; apostrophes need no quoting
MyData$AnswerR <- jencode(MyData, Answer,
                          map = "Yes=1; No=0; Don't know=8; blank=9")
#> Note: This call changes MyData only if you assign the result:
#>   MyData$<name> <- jencode(...)
#> To check the encoding landed correctly, compare jfreq() on the original and the
#> new column.

# Repair mode: keep the numbers at face value, sweep words and blanks
MyData$Age <- jencode(MyData, AgeTxt, map = "else=NA")
#> Note: 3 values in 'AgeTxt' stored as text were kept at their own value
#> ("41" -> 41, never renumbered).
#> 
#> Note: -99 in 'AgeTxt' looks like a coded missing value; the column also
#> contained the word "Refused".
#> Declare -99 with jdeclare_missing() so analyses exclude it.
#> 
#> Note: else=NA converted 1 unmapped word (1 cell) in 'AgeTxt' to missing (NA).
#> The unmapped word was "Refused".
#> 
#> Note: This call changes MyData only if you assign the result:
#>   MyData$<name> <- jencode(...)
#> To check the encoding landed correctly, compare jfreq() on the original and the
#> new column.

# A factor: level order kept; an empty level keeps its code and label
MyData$Sev <- factor(c("Low", "High", "Low", "High"),
                     levels = c("Low", "Medium", "High"))
MyData$SevR <- jencode(MyData, Sev)
#> Note: 'Sev' was encoded in its level order:
#>   "Low"    -> 1
#>   "Medium" -> 2  (no cases)
#>   "High"   -> 3
#> If these categories have a natural order (like Low/Medium/High), rerun with a
#> map to choose the numbers:
#>   MyData$SevR <- jencode(MyData, Sev, map = "Low=1; Medium=2; High=3")
#> 
#> Note: This call changes MyData only if you assign the result:
#>   MyData$<name> <- jencode(...)
#> To check the encoding landed correctly, compare jfreq() on the original and the
#> new column.