Объедините таблицу data.table с различными значениями так, чтобы более короткий набор данных повторял последний ряд до равной длины другого - PullRequest
0 голосов
/ 13 июня 2019

Я не могу связать вывод функции слияния в SAS с какой-либо из известных мне концепций: внутренним, внешним, левым или правым внешним, перекрестным соединением или антисоединением.Я пытаюсь получить вывод в R, но не знаю, как это сделать.

Код объединяет два набора данных, используя одну переменную.Эта переменная имеет одно и то же значение в обоих наборах данных.Насколько я понимаю, это должно быть слияние один-ко-многим, но выход имеет то же количество строк, что и второй набор данных.

Код SAS

data xyz;
merge dt1(in = INA) dt2(in = INB);
by STUDENT;

или

data xyz;
   merge dt1(in = INA) dt2(in = INB);
   by STUDENT;
   if INA = 1; 
run;

Мой код R

dt2<- data.frame(Student = c(6,6,6,6,6,6,6,6,6),

             RollNum2 = c(58,69,45, 38,88,73,33,99,29),

             Marks2= c(8,9,10,3,5,7,8,8,9))


dt1<- data.frame(Student = c(6,6,6),

             RollNum1 = c(49,69,44),

             Marks1= c(8,9,10)) 

Я пытался

xyz <- merge(x   = dt1,
             y   = dt2,
             by  = "Student"
             all = TRUE,
             allow.cartesian = TRUE)

или

xyz <- merge(x   = dt1,
             y   = dt2,
             by  = "STUDENT"
             all.x = TRUE,
             allow.cartesian = TRUE)

или

xyz <- left_join(dt1, dt2, by = c("STUDENT"))

INPUT

dt1

Student RollNum1 Marks1

 6         49             8

 6         69             9

 6         44            10

dt2

Student RollNum2 Marks2

 6          58             8

 6          69             9

 6          45            10

 6          38             3

 6          88             5

 6          73             7

 6          33             8

 6          99             8

 6          29             9

ВЫХОД

ЖЕЛАЕМЫЙ ВЫХОД (КАК ЭТО НАХОДИТСЯ В SAS)

STUDENT RollNum1 Marks1 RollNum1 Marks2

 6          49     8       58              8

 6          69     9       69              9

 6          44    10       45              10

 6          44    10       38              3

 6          44    10       88              5

 6          44    10       73              7

 6          44    10       33              8

 6          44    10       99              8

 6          44    10       29              9

Как мы видим, первые два ряда dt1 связываются с первыми двумя рядами dt2, а для остальных рядов третий ряд dt1 связывается со всемиряды dt2.Конечное количество выходных строк совпадает с количеством строк в dt2.

R вывод с левым слиянием / объединением (НЕ ТРЕБУЕТСЯ ВЫХОД)

ВЫХОД (НЕ ЖЕЛАЕТСЯ - результаты один ко многим с 27 строками)

student roll.no.x marks2.x roll.no.y marks2.y

1: 6 49 8 58 8

2: 6 49 8 69 9

3: 6 49 8 45 10

4: 6 49 8 38 3

5: 6 49 888 5

6: 6 49 8 73 7

7: 6 49 8 33 8

8: 6 49 8 99 8

9: 649 8 29 9

10: 6 69 9 58 8

11: 6 69 9 69 9

12: 6 69 9 45 10

13: 6 69 9 38 3

14: 6 69 9 88 5

15: 6 69 9 73 7

16: 6 69 9 33 8

17: 6 69 9 99 8

18: 6 69 9 29 9

19: 6 44 10 58 8

20: 6 44 10 69 9

21: 6 44 10 45 10

22: 6 44 10 38 3

23: 6 44 10 88 5

24: 6 44 10 73 7

25: 6 44 10 33 8

26: 6 4410 99 8

27: 6 44 10 29 9

Ответы [ 3 ]

2 голосов
/ 13 июня 2019

В SAS оператор (in = variable_name) позволяет вам контролировать тип вашего слияния.dt1 (in = INA) создает переменную, равную 1 в наборе данных dt1, а dt2 (in = INB) делает то же самое для набора данных 2.

С помощью операторов if вы можете теперь контролировать, какие наблюдения выхочу сохранить после слияния.Если вы установите «if INA = 1;», будут сохранены только те строки, которые содержались в dt1.Это эквивалентно left_merge в R. Если вы установите «if INA = 1;»и «если INB = 1;», это будет эквивалентно внутреннему слиянию, поскольку вы будете хранить учеников только в обоих наборах данных.Например, следующее слияние будет левым:

proc sort dt1; by STUDENT; run; 
proc sort dt2; by STUDENT; run;    

data xyz;
   merge dt1(in = INA) dt2(in = INB);
   by STUDENT;
   if INA = 1; 
run; 

Carles Sans Fuentes предоставил перевод dplyr приведенного выше кода SAS.

2 голосов
/ 13 июня 2019

Является ли ваш вопрос, КАК показанный вами шаг данных SAS объединяет данные?

Оператор MERGE (это НЕ функция) в SAS будет считывать одно наблюдение из каждого входа на каждой итерации шага данных. Когда на одном входе заканчиваются наблюдения для этой группы, больше не считываются с этого входа до следующей группы. Таким образом, значения переменных, внесенных этим источником, не меняются.

Когда начинается новая группа (на основе значений переменных BY), тогда все переменные очищаются. Поэтому, если один вход не имеет каких-либо наблюдений для этой группы, то переменные, уникальные для этого входа, будут отсутствовать.

Если между входами есть общие переменные не BY, то значение, загруженное последним, переопределит предыдущие значения. Значения загружаются из входов в том порядке, в котором они перечислены в операторе MERGE. Так что в вашем случае, если DT1 и DT2 оба имеют переменную с именем FRED, тогда значения, загруженные из DT2, будут перезаписывать значения, считанные из DT1. Но если DT1 имеет больше наблюдений для группы, чем DT2, тогда новые значения для FRED из DT1 будут загружены, но не перезаписаны значениями из DT2, так как он прекратил вносить данные для этой группы.

1 голос
/ 13 июня 2019

Я не знаю о существовании функции, которая делает это.

Тем не менее, как я понимаю, вы могли бы сделать функцию такой, что:

  1. Выбор этихпеременные, имеющие столбец Student
  2. Повтор dt1 последнего наблюдения до тех же самых nrow(dt2)
  3. Связывание строк в dt1
  4. Связывание dt1и dt2 по столбцу
  5. Удалить один из Student столбцов

Это должно быть сделано для каждого уникального значения в столбце Student.

Поскольку вы видите его внутреннюю часть, это может быть сделано:

dt1<- data.frame(Student = c(6,6,6,7,7), 
                 RollNum1 = c(49,69,44,86,39), 
                 Marks1= c(8,9,10,8,5)) 
dt2<- data.frame(Student = c(6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7), 
                 RollNum2 = c(58,69,45,38,88,73,33,99,29,58,31,55,58,44,56,89), 
                 Marks2= c(8,9,10,3,5,7,8,8,9,6,9,5,9,3,4,8))

uniquevars<- unique(dt1$Student)
for(i in 1:length(uniquevars)){
  subsetdt1<- dt1[dt1$Student==uniquevars[i],]
  subsetdt2<- dt2[dt2$Student==uniquevars[i],]
  LastRowrep<-as.data.frame(matrix(rep(unlist(subsetdt1[nrow(subsetdt1),]),times=nrow(subsetdt2)-nrow(subsetdt1)),ncol = ncol(subsetdt1), byrow = T))
  colnames(LastRowrep)<-colnames(subsetdt1)
  if(i ==1){Res<-cbind(rbind(subsetdt1,LastRowrep),subsetdt2)}
  else{Res<-rbind(Res,cbind(rbind(subsetdt1,LastRowrep),subsetdt2))}

}
Res
   Student RollNum1 Marks1 Student RollNum2 Marks2
1        6       49      8       6       58      8
2        6       69      9       6       69      9
3        6       44     10       6       45     10
4        6       44     10       6       38      3
5        6       44     10       6       88      5
6        6       44     10       6       73      7
7        6       44     10       6       33      8
8        6       44     10       6       99      8
9        6       44     10       6       29      9
42       7       86      8       7       58      6
52       7       39      5       7       31      9
11       7       39      5       7       55      5
21       7       39      5       7       58      9
31       7       39      5       7       44      3
41       7       39      5       7       56      4
51       7       39      5       7       89      8

Приветствия!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...