Как создать новый столбец в R, который соответствует нескольким значениям из двух разных фреймов данных - PullRequest
2 голосов
/ 10 февраля 2020

У меня есть 2 фрейма данных с тысячами переменных.

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

Teacher Student Age
0123    1       7
0145    1       7
0163    1       7
0175    2       8
0123    2       8
0194    2       8
0123    3       7 
0145    3       7

Тогда у меня есть оценки учителя для определенных c стереотипов относительно разных возрастов. Каждый учитель вносит в рейтинг для каждой возрастной группы стереотип. Фрейм данных выглядит следующим образом.

Teacher Age 7   Age 8  Age 9
0123    1       1      1
0145    5       7      3
0163    4       7      1
0175    6       8      1
0183    3       8      1
0194    2       8      1
0120    3       7      4

Я хочу создать новый столбец в первом фрейме данных, в котором сопоставляются учителя в каждой строке, а значения - это их стереотипный отклик в зависимости от возраста каждого из них. студент. Например, в этом новом столбце значение в первой строке будет ответом стереотипа учителя 123 для 7-летних. В данном случае это 1.

Большое спасибо за вашу помощь. Я новичок в R и понятия не имею, с чего начать.

Редактировать: Я бы хотел, чтобы результат выглядел так:

Teacher Student Age AgeStereotype
0123    1       7   1
0145    1       7   5
0163    1       7   4
0175    2       8   8
0123    2       8   1
0194    2       8   8
0123    3       7   1
0145    3       7   5

Ответы [ 4 ]

1 голос
/ 10 февраля 2020

Эту задачу лучше всего решить, преобразовав второй фрейм данных в длинный фрейм, а затем присоединив его к первому фрейму данных. Существует множество способов выполнить sh в R, вот простой способ сделать это в tidyverse, в частности с dplyr и tidyr функциями.

# Recreating your data
df1 <- tibble::tribble(
  ~Teacher, ~Student, ~Age,
   "0123",    1,       7,
   "0145",    1,       7,
   "0163",    1,       7,
   "0175",    2,       8,
   "0123",    2,       8,
   "0194",    2,       8,
   "0123",    3,       7,
   "0145",    3,       7
  )

df2 <- tibble::tribble(
  ~Teacher, ~Age.7, ~Age.8, ~Age.9,
     "0123",    1,       1,      1,
     "0145",    5,       7,      3,
     "0163",    4,       7,      1,
     "0175",    6,       8,      1,
     "0183",    3,       8,      1,
     "0194",    2,       8,      1,
     "0120",    3,       7,      4
  )

# Load necessary libs
library(dplyr, warn.conflicts = FALSE)
library(tidyr)

tidyr::pivot_longer() преобразует df2 в длинный формат, а dplyr::mutate() с gsub() и as.numeric() используются для сброса остатка из имен переменных и преобразования в объединения dbl.

df2_long <-
  df2 %>%
  pivot_longer(Age.7:Age.9,
               names_to = "Age",
               values_to = "AgeStereotype") %>%
  mutate(Age = as.numeric(gsub("Age.", "", Age)))

dplyr::left_join() наборы данных, содержащие только тех учителей, у которых есть строка в df1.

left_join(df1, df2_long)
#> Joining, by = c("Teacher", "Age")
#> # A tibble: 8 x 4
#>   Teacher Student   Age AgeStereotype
#>   <chr>     <dbl> <dbl>         <dbl>
#> 1 0123          1     7             1
#> 2 0145          1     7             5
#> 3 0163          1     7             4
#> 4 0175          2     8             8
#> 5 0123          2     8             1
#> 6 0194          2     8             8
#> 7 0123          3     7             1
#> 8 0145          3     7             5
1 голос
/ 10 февраля 2020

Вы можете использовать [ ie:

transform(df1,AgeStereotype = `rownames<-`(df2,df2$Teacher)[cbind(Teacher,paste("Age",Age))])

  Teacher Student Age AgeStereotype
1     123       1   7             1
2     145       1   7             5
3     163       1   7             4
4     175       2   8             8
5     123       2   8             1
6     194       2   8             8
7     123       3   7             1
8     145       3   7             5
1 голос
/ 10 февраля 2020
AS <- apply(DF1[,c("Teacher", "Age")], 1, function(x) {
    DF2[which(DF2$Teacher == x[1]), which(grepl(x[2], names(DF2)))]
    })
DF1["AgeStereotype"] <- AS

с DF1 и DF2 вашим первым и вторым кадрами данных соответственно.

Вывод:

  Teacher Student Age AgeStereotype
1     123       1   7             1
2     145       1   7             5
3     163       1   7             4
4     175       2   8             8
5     123       2   8             1
6     194       2   8             8
7     123       3   7             1
8     145       3   7             5
0 голосов
/ 10 февраля 2020

Другой base путь:

merge(
  df1,
  data.frame(Teacher = df2$Teacher, 
             Age = gsub("[[:alpha:]]", "", stack(df2[,-1])[,2]),
             AgeStereotype = stack(df2[,-1])[,1]
  )
)

Вывод:

  Teacher Age Student AgeStereotype
1     123   7       1             1
2     123   7       3             1
3     123   8       2             1
4     145   7       1             5
5     145   7       3             5
6     163   7       1             4
7     175   8       2             8
8     194   8       2             8

Это меняет первоначальный порядок, хотя, и даже если это возможно изменить без дополнительных пакетов, если это важно, возможно, проще всего просто позволить dplyr выполнить соединение:

dplyr::left_join(
  df1,
  data.frame(Teacher = df2$Teacher, 
             Age = as.integer(gsub("[[:alpha:]]", "", stack(df2[,-1])[,2])),
             AgeStereotype = as.integer(stack(df2[,-1])[,1]), stringsAsFactors = FALSE
  )
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...