присвоение значений в новом столбце — эффективность, пожалуйста

#r #dataframe #assign

#r #фрейм данных #присвоить

Вопрос:

Я ищу более эффективный способ выполнения очень простой задачи: добавление нового столбца со значениями, указанными для существующих строк. Образец фрейма данных (называемый ess) имеет страны и (обзор) раунд. Я хочу добавить столбец «dem» со значениями из внешнего источника. Вот фрагмент:

 id cntry essround dem
1 AL       1
2 AT       1
3 BE       1
4 BG       1
5 HR       1
6 AL       2
7 AT       2
8 BE       2
9 BG       2
10 HR      2
  

«Длинный» способ сделать это заключается в следующем:

 ess$dem <- NA
ess$dem[ess$cntry=="AL" amp; ess$essround==1] <- 3.5
ess$dem[ess$cntry=="AT" amp; ess$essround==1] <- 1
ess$dem[ess$cntry=="BE" amp; ess$essround==1] <- 1.5
ess$dem[ess$cntry=="BG" amp; ess$essround==1] <- 2
ess$dem[ess$cntry=="HR" amp; ess$essround==1] <- 2
ess$dem[ess$cntry=="AL" amp; ess$essround==2] <- 3
ess$dem[ess$cntry=="AT" amp; ess$essround==2] <- 1
ess$dem[ess$cntry=="BE" amp; ess$essround==2] <- 1
ess$dem[ess$cntry=="BG" amp; ess$essround==2] <- 1.5
ess$dem[ess$cntry=="HR" amp; ess$essround==2] <- 2
  

Проблема в том, что этот способ выполнения становится очень длинным, когда у меня 36 стран и 6 раундов — таким образом, у меня получается 216 строк кода. (Становится хуже, когда я хочу создать несколько новых столбцов в одном и том же режиме …)

Нет ли способа сжать подобную операцию?? Можно ли это сделать в одной строке, где код зависит от «позиции» в соответствующих списках значений?

Комментарии:

1. Вы ищете ess$dem <- c(3.5, 1, 1.5, 2, 2, 3, 1, 1, 1.5, 2) ?

2. хорошо, можете ли вы дать нам какой-нибудь пример df для работы? как dem выглядит ограничение df?

Ответ №1:

tidyverse Сначала вам нужно создать data.frame, который будет содержать значения: ie ess$dem[ess$cntry=="AL" amp; ess$essround==1] <- 3.5 должен стать строкой в conds data.frame:

 ## expand grid to create all possible combinations of cntry and essround
conds <- expand.grid(cntry=c("AL","AT","BE","BG","HR"), essround=1:2) %>% mutate(dem = c(3.5,1,1.5,2,2,3,1,1,1.5,2))
## first row will be "AL" 1 3.5 which is the first condition
conds
   cntry essround dem
1     AL        1 3.5
2     AT        1 1.0
3     BE        1 1.5
4     BG        1 2.0
5     HR        1 2.0
6     AL        2 3.0
7     AT        2 1.0
8     BE        2 1.0
9     BG        2 1.5
10    HR        2 2.0
ess %>% left_join(conds)
Joining, by = c("cntry", "essround")
   cntry essround dem
1     AT        1 1.0
2     AT        2 1.0
3     HR        2 2.0
4     BG        2 1.5
5     HR        2 2.0
6     HR        1 2.0
7     BG        2 1.5
8     BG        1 2.0
9     HR        2 2.0
10    BG        1 2.0
11    AT        1 1.0
12    BG        2 1.5
13    AL        1 3.5
14    HR        1 2.0
15    BE        2 1.0
16    AL        2 3.0
17    AL        1 3.5
18    AL        1 3.5
19    AT        1 1.0
20    AT        1 1.0
  

Комментарии:

1. Спасибо — это работает. Left_join — теперь я понял. Я настроил второй фрейм данных (содержащий «условия») в Excel — это достаточно просто и лучше, чем иметь сотни строк кода…

2. @dbartram также по умолчанию будут назначены строки, у которых нет условия соответствия NA

Ответ №2:

Создание фиктивных данных:

 ess = data.frame(
contry = sample(c("AL","AT","BE","BG","HR","AL","AT","BE","BG","HR"), 20, TRUE),
essround = sample(1:2, 20, TRUE))
  

Теперь код:

 ess$dem <- NA

values = c(3.5,1,1.5,2,2,3,1,1,1.5,2)
groups = unique(ess$contry)

for(i in 1:length(groups)){
  ess[ess$contry==groups[i],"dem"] <- values[i]
}
  

Вывод:

    contry essround dem
1      BE        1 3.5
2      HR        2 1.0
3      AT        2 1.5
4      BG        1 2.0
5      AT        1 1.5
6      AT        2 1.5
7      AT        2 1.5
8      AT        2 1.5
9      BG        2 2.0
10     BE        2 3.5
11     AT        1 1.5
12     AT        2 1.5
13     BE        1 3.5
14     AT        2 1.5
15     HR        1 1.0
16     BG        1 2.0
17     BE        1 3.5
18     BG        1 2.0
19     AT        2 1.5
20     AT        2 1.5