Как выбрать элемент из матрицы в зависимости от набора условий? - PullRequest
0 голосов
/ 09 июля 2020

У меня есть фрейм данных, содержащий n строк и m столбцов. Каждая строка индивидуальна, и каждый столбец содержит информацию об этом человеке.

df

id   age   income 
1    18     12
2    24     24
3    36     12
4    18     24
.    .      .
.    .      .
.    .      .

У меня также есть матрица r X c, показывающая сегменты возраста в каждой строке и сегменты дохода в каждом столбце и каждом элементе матрицы - это процент людей для каждого сегмента дохода-возраста.

matrix age\income

     12    24    36  .....
18  0.15  0.12  0.11 ....
24  0.12  0.6   0.2  ...
36  0.02  0.16  0.16 ...
.    ..................
.    ..................

Для каждого человека в кадре данных мне нужно найти правильный элемент матрицы, учитывая возраст и сегмент дохода человека .

Желаемый результат должен выглядеть так

df2

id   age   income  y
1    18     12    0.15
2    24     24    0.6
3    36     12    0.02
4    18     24    0.12
.    .      .
.    .      .
.    .      .

Я пробовал с серией IF внутри al oop (как в примере):

for (i in 1:length(df$x)) {
  workingset <- df[i,]
    if(workingset$age==18){
      temp<-marix[1,]
      workingset$y <- ifelse(workingset$income<12, temp[1], ifelse(workingset$income<24,temp[2],ifelse,temp[3])
}else if(workingset$age==24){
      temp<-marix[2,]
      workingset$y <- ifelse(workingset$income<12, temp[1], ifelse(workingset$income<24,temp[2],ifelse,temp[3])
}else if{
...
}
  if(i==1){
    df2 <- workingset
  }else{
    df2<- rbind(df2, workingset)
  }
}

Этот код работает, но занимает слишком много времени. Есть ли способ выполнить эту работу эффективно?

1 Ответ

1 голос
/ 09 июля 2020

Предполагая, что ваши данные выглядят точно так, как показано, вы можете использовать dplyr и tidyr.

Сначала преобразуйте вашу матрицу (я называю ее my_mat) в data.frame

my_mat %>% 
  as.data.frame() %>%
  mutate(age=rownames(.)) %>%
  pivot_longer(cols=-age, names_to="income", values_to="y") %>%
  mutate(across(where(is.character), as.numeric))  

возвращает

# A tibble: 9 x 3
    age income     y
  <dbl>  <dbl> <dbl>
1    18     12  0.15
2    18     24  0.12
3    18     36  0.11
4    24     12  0.12
5    24     24  0.6 
6    24     36  0.2 
7    36     12  0.02
8    36     24  0.16
9    36     36  0.16

Это можно оставить вместе с вашим data.frame df, поэтому в одном go:

my_mat %>% 
  as.data.frame() %>%
  mutate(age=rownames(.)) %>%
  pivot_longer(cols=-age, names_to="income", values_to="y") %>%
  mutate(across(where(is.character), as.numeric)) %>%
  left_join(df, ., by=c("age", "income"))

вы получите

# A tibble: 4 x 4
     id   age income     y
  <dbl> <dbl>  <dbl> <dbl>
1     1    18     12  0.15
2     2    24     24  0.6 
3     3    36     12  0.02
4     4    18     24  0.12

Данные

my_mat <- structure(c(0.15, 0.12, 0.02, 0.12, 0.6, 0.16, 0.11, 0.2, 0.16
), .Dim = c(3L, 3L), .Dimnames = list(c("18", "24", "36"), c("12", 
"24", "36")))

df <- structure(list(id = c(1, 2, 3, 4), age = c(18, 24, 36, 18), income = c(12, 
24, 12, 24)), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -4L), spec = structure(list(cols = list(
    id = structure(list(), class = c("collector_double", "collector"
    )), age = structure(list(), class = c("collector_double", 
    "collector")), income = structure(list(), class = c("collector_double", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
"collector")), skip = 1), class = "col_spec"))
...