2015-03-04 4 views
2

Я хочу использовать набор данных B, чтобы перезаписать некоторые значения в наборе данных A путем слияния набора данных A & B с идентификатором слияния. Однако он не работает должным образом. Вот тест я сделал:SAS объединяет наборы данных для перезаписывания значений

/* create table A */ 
data a; 
    infile datalines; 
    input id1 $ id2 $ var1; 
datalines; 
    1 a 10 
    1 b 10 
    2 a 10 
    2 b 10 
; 
run; 

/* create table B */ 
data b; 
    infile datalines; 
    input id1 $ var1 var2; 
datalines; 
    1 20 30 
    2 20 30 
; 
run; 

/* merge A&B to overwrite var1 in table A using values in table B */ 
data c; 
    merge a b; 
    by id1; 
run; 

Таблица C выглядит следующим образом:

ID1 ID2 VAR1 VAR2 

1 a  20 30 

1 b  10 30 

2 a  20 30 

2 b  10 30 

Почему 10s в строке 2 & 4 не заменяются на 20 из таблицы B? Пока var2 работает так, как ожидалось?

Я знаю, что могу сделать это просто с помощью proc SQL, и это то, что я сделал для решения проблемы. Но мне все еще очень интересно, есть ли способ сделать то, что я хотел использовать слияние? И почему это не работает? Я предпочитаю слияние с SQL в этом случае, потому что логика проще реализовать (я считаю, что это не работает должным образом).

Я использую SAS 9.4.

+0

У вас есть повторяющиеся значения 'id1' в таблице A. Я думаю, что нет никакого подхода simpe, используя любое слияние/обновление/изменение для достижения этого. – Lovnlust

+0

Не используйте фрагменты кода с чем-либо, кроме языков, с которыми они явно работают (в основном, html/javascript/etc.). – Joe

+0

Также уместно (но не точное дублирование), http://stackoverflow.com/questions/25251177/when-using-multiple-datasets-in-a-set-or-a-merge-with-duplicate-by-values -почему-д – Joe

ответ

1

Метод merge все еще может работать нормально, вам просто нужно будет более четко о том, как выбрать «лучший» значение var1, такие как:

data c (drop = a_var1 b_var1); 
    merge a(rename=(var1 = a_var1)) 
      b(rename=(var1 = b_var1)); 
    by id1; 
    * Now you have two different variables named a_var1 and b_var1; 
    * Implement logic to choose your favorite; 
    if NOT MISSING(b_var1) Then DO; 
     var1 = b_var1; 
     var1_source='B'; 
    END; 
    else DO; 
     var1 = a_var1; 
     var1_source='A'; 
    END; 
run; 

Если ваши критерии, по которым «var1» для выбора так же просто, как «Если b существует, используйте его», то это идентично методу SQL с coalesce().

Где я нашел этот метод полезен для более сложных критериев, плюс его всегда приятно знать источник данных (чего не бывает с coalesce()).

2

Это связано с тем, как SAS выполняет итерации над наборами данных во время слияния. В принципе, вторая запись для каждого из A не выравнивается с записью из B. Значение VAR2 переносится с предыдущей записи. VAR1 получает свое значение от A (потому что нет B).

IF есть запись в B для КАЖДОЙ ID1, то вы можете переписать слияние, как это добиться того, что вы хотите.

/* merge A&B to overwrite var1 in table A using values in table B */ 
data c; 
    merge a(drop=var1) b; 
    by id1; 
run; 

Это роняет VAR1 из А так, что она осуществляется вниз от записи в Б.

В противном случае вам потребуется более сложная логика (я бы предложить SQL LEFT JOIN с функцией coalesce()?) ,

2

Как и в случае с DomPazz, proc sql - это способ сделать это. merge сохранит только одно значение из каждого набора данных. Функция coalesce выбирает первое не пропущенное значение из списка, поэтому оно использует var1 от b, но если b.var1 имеет значение null, то он использует a.var1.

proc sql; 
create table c as 
select 
    a.id1, 
    a.id2, 
    coalesce(b.var1,a.var1) as var1, 
    b.var2 
from 
    a 
    left join b 
    on a.id1 = b.id1 
; 
quit; 
Смежные вопросы