Я совершенно новичок в SAS, и мне нужно выполнить простую задачу. скажем, у меня есть таблица вроде:
Мне нужно удалить все экземпляры sampCode
, для которых хотя бы один SampCode
отражает условие:
2*res > max
. то есть удаление не только строки, но и всей группы sampCode
на основе этого условия.
Спасибо за помощь!
ты прав. Я заменил стол. Теперь для второй строки результат> 2*res > max
, поэтому вывод не должен содержать ни одной записи 2014_AT14012534-001
. надеюсь, теперь стало понятнее. Спасибо
Попробуйте использовать двойной DoW Loop.
Предполагается, что ваш набор данных отсортирован по sampCode
.
data want;
_keep=1;
do _n_=1 by 1 until (last.sampCode);
set have;
by sampCode;
if 2*res>max then _keep=0;
end;
do _n_=1 by 1 until (last.sampCode);
set have;
by sampCode;
if _keep=1 then output;
end;
drop _keep;
run;
В результате 2014_AT14012534-001
и 2014_AT14044069-001
удаляются.
sampCode res max
2014_AT14036758-001 0.01 0.066
2014_AT14051994-001 0.01 0.021
2014_BE2549-14-0021 0.01 0.33
2014_BE2549-14-0023 0.01 0.06
2014_BE3013-14-0118 0.01 0.044
2014_BE3259-14-0019 0.01 0.1
2014_BE3259-14-0101 0.01 0.037
2014_BE3320-14-0200 0.01 0.038
2014_BE3365-14-0005 0.01 0.021
2014_BE4040-14-0548 0.005 0.11
2014_BE4685-14-0018 0.01 0.054
2014_BE4804-14-0057 0.01 0.18
2014_BE4824-14-0007 0.01 0.03
Для подхода SQL попробуйте
proc sql;
create table want as
select sampCode, res, max
from (select sampCode, res, max,
max(case when 2*res>max then 1 else 0 end) as _max
from have
group by sampCode
having _max=0);
quit;
Если есть повторяющийся sampCode (например, 2014_AT14012534-001), у вас не будет всех наблюдений. Вам нужна двойная петля DoW.
Для данного его примера это не имеет значения, но в общем случае так и есть. Спасибо !
Первый индекс цикла _n_
будет вычислять размер группы в конце цикла. Второй цикл может быть простым _n_ = 1 to _n_;
и не требует оператора BY
внутри.
Вы должны использовать двойной DOW, иначе вы получите только одно наблюдение на sampCode, даже в тех случаях, когда имеется множество наблюдений с одним и тем же sampCode.
data have;
informat sampCode $40.;
input sampCode res max;
datalines;
2014_AT14012534-001 0.01 0.034
2014_AT14012534-001 2 0.144
2014_AT14012534-001 0.01 0.015
2014_AT14012534-001 0.01 0.075
2014_AT14012534-002 0.01 0.034
2014_AT14012534-002 0.01 0.314
2014_AT14012534-003 0.01 0.034
2014_AT14012534-003 0.02 0.934
2014_AT14012534-003 0.01 0.034
2014_AT14012534-004 3 0.001
run;
data want;
keep=1;
do until (last.sampCode);
set have;
by sampCode;
if 2*res>max then keep=0;
end;
do until (last.sampCode);
set have;
by sampCode;
if keep=1 then output;
end;
drop keep;
run;
Большое спасибо. Я попробую, но, поскольку в моих данных есть несколько строк 4M, подход do кажется слишком дорогим, хотя... Я думал, что это можно сделать с помощью некоторой процедуры sql
@efz Во многих случаях цикл DoW более эффективен, чем использование процедуры SQL. Я все равно отредактировал свой ответ с помощью SQL.
в следующий раз, если вы ищете ответ SQL, укажите это в вопросе и добавьте тег proc-sql
Чтобы проверить, истинно ли логическое выражение для ряда значений, просто используйте MAX(). SAS оценивает логические выражения как 1 (истина) или 0 (ложь). Таким образом, MAX() является истинным, если какое-либо значение истинно. В вашем случае вы хотите сохранить наблюдения, в которых условие никогда не выполняется, поэтому, когда MAX() является ложным.
PROC SQL с радостью объединит сводную статистику со всеми подробными наблюдениями.
select *
from have
group by sampcode
having not max(2*res > max)
;
А что такое группа sampCode? Ваш sampCode имеет разное значение для каждой строки. Показать желаемый результат.