Kumulieren, aber in Intervallen

Hallo, folgendes Problem:

Mein Datensatz besteht aus 3 Variablen:
Kennzeichen (character), Index (numeric) und Wert (numeric).
Ich habe 20 verschiedene Kennzeichen mit jeweils immer 50 Indices und einem Wert dazu. Sieht also etwa so aus:

k01 1 w01_01
k01 2 w01_02
...
k01 50 w01_50
k02 1 w02_01
...
k02 50 w02_50
k03 1 w03_01
...
k20 50 w20_50

Nur die Werte pro Kennzeichen aufzusummieren ist kein Problem, aber ich brauche nun folgendes:
'
Eine vierte Variable, die mir anzeigt, wie groß die Summe der Werte in der Umgebung +/- 4 ist, also eine Variable, die durch die Addition der vier vorhergehenden Werte, der vier folgenden Werte und dem aktuellen Wert entsteht.

Bei k01 1 also nur die Summe von w01_01 bis w01_05.
Bei k01 2 dann die Summe von w01_01 bis w01_06.
Bei k01 20 brauche ich die Summe der vier Werte davor (Summe w01_16-w01_19, den Wert selbst (w01_20) und die vier folgende noch dazu Summe w01_21-w01_24.
Bei k01 50 dann nur noch den Wert selbst plus die vier Werte davor.
Für die folgenden Kennzeichen dann entsprechend.

Versteht mich überhaupt jemand und/oder hat jemand eine Idee? :)

MfG

Daten erst vervielfältigen, dann wieder zusammenfassen

/* Beispieldaten erzeugen */
data problem (drop=k);
   
length kennzeichen $3;
   
do k=1 to 20;
      
do index=1 to 50;
         kennzeichen =
'k' !! put (k, z2.);
         wert = round(ranuni(
1)*1000,1.0);
         
output;
      
end;
   
end;
run;

/* Datei "aufblähen", View nur aus Performancegründen */
data loesung_view (drop=index rename=(index2=index)) / view=loesung_view;
   
retain kennzeichen index2 wert; /* nur wegen Variablenreihenfolge */
   
set problem;
   
do index2=max(1,index-4) to min(50,index+4);
      
output;
   
end;
run;

/* jetzt wieder zusammenfassen */
proc means noprint nway;
   
class kennzeichen index;
   
var wert;
   
output out=loesung (drop=_type_ _freq_)sum=;
run;

Warum einfach, wenn es auch kompliziert geht ;-)

... darum hat es auch länger gedauert.
Hier eine Lösung in einem Schritt, ohne Aufblähen:


data intervall;
input knz $ id wert;
cards;
k01 1 2
k01 2 3
k01 3 6
k01 4 9
k01 5 20
k02 1 7
k02 2 6
k02 3 9
k02 4 10
k02 5 2
;
run;

proc sort data=intervall;
by knz id;
run;
options mprint mlogic;
%macro t;

%let n=2; /* Anzahl der Kennzeichen */
%let i=5; /* Indices */

data summe(keep=knz id wert summe);
set intervall(rename=(knz=knz_in id=id_in wert=wert_in)) end=lastrec;
by knz_in;
array _w(
1:&n.,1:&i.) %do _n = 1 %to &n.;

                        w&_n._1-w&_n._&
i.
                        
%end;
                      ;
array _s(
1:&n.,1:&i.) %do _n = 1 %to &n.;

                        s&_n._1-s&_n._&
i.
                        
%end;
                      ;

array _k(
1:&n.) $ k1-k&n.;
retain _w _k;
if _n_=
1 then do;
  i=
1;
end;
if first.knz_in then do;
  _k(i)=knz_in;
end;
_w(i,id_in)=wert_in;
if last.knz_in then do;
  i+
1;
end;
if lastrec then do;
  do i =
1 to &n.;
    do j =
1 to &i.;
      first = max(j-
1,1);
      last  = min(j+
1,5);
      _s(i,j)=
0;
      do k = first to last;
        _s(i,j)+_w(i,k);
      end;
      knz=_k(i);
      id=j;
      wert=_w(i,j);
      summe=_s(i,j);
      output;
    end;
  end;
end;
run;

%mend t;
%t

Ist nur leider nicht so elegant, wie die Lösung von Herrn Mangold, die Makroparameter n, i und die Intervallgröße (j-1,j+1) müssen angepasst, oder wie auch immer flexibel bestimmt werden.

Gruß
Wolfgang Hornung

Anpassungen

Wenn ich die Zeilen

      first = max(j-1,1);
      last  = min(j+1,5);

durch

      first = max(j-4,1);
      last  = min(j+4,&i);

erhalte ich auch mit meinem Daten bei n=20 und i=50 die gleichen Ergebnisse wie in meiner Lösung (bis auf die Tatsache, dass ich vergessen habe, zur Summe den ursprünglichen Wert hinzuzunehmen).

weitere Anpassungen ...

wenn man die Arrays als _temporary_ definiert, die letztendlich transponierten Ausgangswerte interessieren einen sowieso nicht, dann kann man auch noch ordentlich Performance herausholen, bzw. wird es so erst lauffähig sobald man mehr als 32768 Variablen hat. Solange der Speicher mitspielt muss die Ein-Datastep-Lösung den Vergleich mit dem Proc Means nicht scheuen, ist sogar um einiges schneller.