Как применить функцию к ячейке в зависимости от значения ячейки в R?

#r #function #loops

#r

Вопрос:

У меня есть фрейм данных, который выглядит следующим образом:

     Size count Density
1  large    12      NA
2  medium     7      NA
3  small     4      NA
4  large    68      NA
5  medium    53      NA
6  small    25      NA
7  large   139      NA
8  medium    85      NA
9  small    47      NA
10 large   148      NA
11 medium    88      NA
12 small    39      NA
  

Я пытаюсь вычислить столбец плотности. Итак, если размер большой, я хочу разделить количество на 225. Если размер средний, разделите количество на 144, а если размер маленький, разделите количество на 49.

Я понятия не имею, как бы я это сделал, поэтому буду признателен за любую помощь!

Ответ №1:

Мне нравится создавать справочные таблицы для подобных вещей. Я считаю, что это легко проверить и отладить:

 density_lookup = data.frame(
  size = c("large", "medium", "small"),
  denominator = c(225, 144, 49)
)

## Inspect, make sure it looks right
density_lookup
#     size denominator
# 1  large         225
# 2 medium         144
# 3  small          49

# With base R
your_data = merge(your_data, density_lookup, by = "size", all.x = TRUE)
your_data$Density = with(your_data, count / denominator)

# with dplyr
library(dplyr)
your_data %>%
  left_join(density_lookup, by = "size") %>%
  mutate(Density = count / denominator)
  

Вы также можете использовать именованные векторы или ifelse() операторы, но мне нравится этот подход, потому что он очень хорошо обобщает — при необходимости вы можете сопоставить несколько столбцов. Вы можете сохранить поиск в файле CSV, если хотите поделиться им с пользователями, не являющимися R.

Ответ №2:

Если классы не слишком большие, вы можете использовать ifelse() , хотя решение @GregorThomas более практично:

 #Base R
df$Density <- ifelse(df$Size=='large',df$count/225,
                     ifelse(df$Size=='medium',df$count/144,df$count/49))
  

Вывод:

      Size count    Density
1   large    12 0.05333333
2  medium     7 0.04861111
3   small     4 0.08163265
4   large    68 0.30222222
5  medium    53 0.36805556
6   small    25 0.51020408
7   large   139 0.61777778
8  medium    85 0.59027778
9   small    47 0.95918367
10  large   148 0.65777778
11 medium    88 0.61111111
12  small    39 0.79591837
  

Некоторые используемые данные:

 #Data
df <- structure(list(Size = c("large", "medium", "small", "large", 
"medium", "small", "large", "medium", "small", "large", "medium", 
"small"), count = c(12L, 7L, 4L, 68L, 53L, 25L, 139L, 85L, 47L, 
148L, 88L, 39L), Density = c(0.0533333333333333, 0.0486111111111111, 
0.0816326530612245, 0.302222222222222, 0.368055555555556, 0.510204081632653, 
0.617777777777778, 0.590277777777778, 0.959183673469388, 0.657777777777778, 
0.611111111111111, 0.795918367346939)), row.names = c("1", "2", 
"3", "4", "5", "6", "7", "8", "9", "10", "11", "12"), class = "data.frame")
  

Ответ №3:

Это тоже работает

 within(df1, Density <- count / c("large" = 225, "medium" = 144, "small" = 49)[Size])
  

Вывод

 # A tibble: 12 x 3
   Size   count Density
   <chr>  <dbl>   <dbl>
 1 large     12  0.0533
 2 medium     7  0.0486
 3 small      4  0.0816
 4 large     68  0.302 
 5 medium    53  0.368 
 6 small     25  0.510 
 7 large    139  0.618 
 8 medium    85  0.590 
 9 small     47  0.959 
10 large    148  0.658 
11 medium    88  0.611 
12 small     39  0.796