1
\$\begingroup\$

I'm replaced character strings with numeric codes in R. I find myself doing a lot of copying and pasting, so there's probably a better solution with apply, sapply, or ddply that I'm missing.

Here's an example:

example <- data.frame(matrix(nrow = 20, ncol = 20))
example[,1]  <- 30:49 
example[,10] <- 10:29 
example[,2]  <- c("apple", "banana", "gum", "steak", "apple", "banana", "gum", "steak",
                  "apple", "banana", "gum", "steak", "apple", "banana", "gum", "steak",
                  "apple", "banana", "gum", "steak")
example[,3:9]  <- c("banana", "gum", "steak", "apple", "banana", "gum", "steak",
                    "banana", "gum", "steak", "apple", "banana", "gum", "steak",
                    "banana", "gum", "steak", "apple", "apple", "apple")
example[,11:20]  <- c("apple", "banana", "gum", "steak", "apple", "banana", "gum", "steak",
                      "apple", "banana", "gum", "steak", "apple", "banana", "gum", "steak",
                      "apple", "banana", "gum", "steak")
names(example) <- c("ID", "food_day_1", "food_day_2", "food_day_3", "food_day_4",
                    "food_day_5", "food_day_6", "food_day_7", "food_day_8",
                    "Some_Numeric_Code", "otherfood_day_1", "otherfood_day_2", 
                    "otherfood_day_3", "otherfood_day_4", "otherfood_day_5", 
                    "otherfood_day_6", "otherfood_day_7", "otherfood_day_8", 
                    "otherfood_day_9",  "otherfood_day_10")

which looks like:

> head(example)
  ID food_day_1 food_day_2 food_day_3 food_day_4 food_day_5 food_day_6 food_day_7 food_day_8 Some_Numeric_Code otherfood_day_1
1 30      apple     banana     banana     banana     banana     banana     banana     banana                10           apple
2 31     banana        gum        gum        gum        gum        gum        gum        gum                11          banana
3 32        gum      steak      steak      steak      steak      steak      steak      steak                12             gum
4 33      steak      apple      apple      apple      apple      apple      apple      apple                13           steak
5 34      apple     banana     banana     banana     banana     banana     banana     banana                14           apple
6 35     banana        gum        gum        gum        gum        gum        gum        gum                15          banana
  otherfood_day_2 otherfood_day_3 otherfood_day_4 otherfood_day_5 otherfood_day_6 otherfood_day_7 otherfood_day_8 otherfood_day_9
1           apple           apple           apple           apple           apple           apple           apple           apple
2          banana          banana          banana          banana          banana          banana          banana          banana
3             gum             gum             gum             gum             gum             gum             gum             gum
4           steak           steak           steak           steak           steak           steak           steak           steak
5           apple           apple           apple           apple           apple           apple           apple           apple
6          banana          banana          banana          banana          banana          banana          banana          banana
  otherfood_day_10
1            apple
2           banana
3              gum
4            steak
5            apple
6           banana

Here's what I did:

example$food_day_1[example$food_day_1 %in%
                            c("apple", "banana")] <- 1
example$food_day_1[example$food_day_1 %in%
                     c("gum", "steak")] <- 2

and so on.

What should I have done?

\$\endgroup\$
  • 1
    \$\begingroup\$ If you leave your data in matrix form, you can do a vectorized replacement replace(example[,-1], example[,-1] %in% c("apple", "banana"), 1) \$\endgroup\$ – Vlo Jun 29 '15 at 19:49
  • \$\begingroup\$ Will you be applying the exact same transformation to food_day_2, ..., food_day_7, otherfood_day_1, ..., otherfood_day_10? Or are the fruit-to-integer mappings column dependent? \$\endgroup\$ – flodel Jun 29 '15 at 23:22
  • \$\begingroup\$ @flodel they were not column dependent, though the order that the elements appear in the column varies by column \$\endgroup\$ – Hack-R Jun 30 '15 at 13:26
1
\$\begingroup\$

You could first create a mapping using a named vector:

map <- c("apple" = 1, "banana" = 1, "gum" = 2, "steak" = 2)

Then create a vector of all the variable names that need to be modified:

vars <- c(paste0("food_day_", 1:7),
          paste0("otherfood_day_", 1:10))

Then modify the data as follows:

example[vars] <- map[unlist(example[vars])]

(where unlist transforms the data.frame example[vars] into a single long vector.)

An interesting aspect of that approach, apart from its conciseness, is that it guarantees than the output columns become numeric. Whereas your approach, by making incremental changes to the columns, would preserve the original class of your columns, i.e. "character". Also note that foods that are not included in the map vector will be turned to NA since for example map["pineapple"] is NA.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.