I came across the code pasted below a couple of years back and have been using it ever since. It has the advantage that you can apply it also to {x,y} data right away. (BTW, it looks like PH Lundow's code below, last updated back in 2007, is in parts very similar to the one posted by John...)
Best,
Frank
PS
I just noticed, that the built-in SavitzkyGolayMatrix function does not seem to be capable of generating higher order (>2) derivatives. So it makes perfectly sense to use a separate package for the task even if it's slower.
(* :Title: Smooth *) (* :Context: "Smooth`" *) (* :Author: P.H. Lundow Bug reports to [email protected] *) (* :Summary: Functions for smoothing equidistant data with a Savitsky-Golay filter. *) (* :History: 020507 Created. 030417 Smooth extended to lists of y-values. 030425 Added SmoothAll. 030619 Added MinimumDistance and EquidistantData. 030923 Small improvement in SGKernel. 070618 Clean-up. *) (* :Mathematica Version: 4.0 *) (* :Keywords: *) (* :Limitations: *) (* :Discussion: There is room for improvement here. Returned list of smoothed data is shorter than original list. Find a better way to produce many kernels that takes care of the margins. *) BeginPackage["Smooth`"] SGKernel::usage = "SGKernel[left, right, degree, derivative] returns the Savitsky-Golay kernel used by the function Smooth when convoluting the data. The kernel has length left+right+1. Left is the number of leftward data points and right is the number of rightward points. Degree refers to the degree of the polynomial and derivative is the order of the desired derivative.\nRef: Numerical Recipes, chapter 14.8." Smooth::usage = "Smooth[list, window, degree, derivative] returns the smoothed form of equally spaced and sorted data. This is done by fitting polynomials of a given degree to a moving window of the list. Argument list is either a list of pairs {{x1,y1},{x2,y2},...} or a list {y1,y2,...} where the x-values are taken to be 1,2,3... If a derivative of the data is desired then give the order of the derivative, default is 0. \nExample:\n a=Table[{x,Sin[x]+Random[Real,{-1,1}],{x,0,2*Pi,0.001}]; \n b=Smooth[a,15,2]; \n c=Smooth[a,15,2,1]; \n This fits 2:nd degree polynomials to moving windows of width 15 to the data. List b is the smoothed data and list c is the derivative of the data." SmoothAll::usage = "SmoothAll[{vector,matrix}, window, degree, derivative] works like Smooth except that vector is a list of x-values and matrix is a list of lists of y-values at the corresponding x-values. The result is returned on the same form.\nExample:\n xold={1,2,3,4,5}; \n yold={{1,3,5,4,4},{2,3,3,2,1},{3,4,6,4,3}}; \n {xnew,ynew}=SmoothAll[{xold,yold},2,1,0];" MinimumDistance::usage = "MinimumDistance[data] returns the minimum distance between two x-values in the data which is a list of lists. The x-values are the first positions of each sublist." EquidistantData::usage = "EquidistantData[data] extracts the largest chunk of equidistant data from a list of lists.\nExample:\n EquidistantData[{{0,1},{2,8},{3,7},{4,9},{6,3}}] returns the list\n {{2,8},{3,7},{4,9}}." Begin["`Private`"] definitions = {MinimumDistance, EquidistantData, SGKernel, Smooth, SmoothAll} Scan[Unprotect, definitions] MinimumDistance[data:{__List}] := Module[{x}, x = Map[First, data]; Min[Drop[x, 1] - Drop[x, -1]] ] EquidistantData[data:{__List}] := Module[{min, len, pos, tmp}, min = MinimumDistance[data]; tmp = Split[data, (#1[[1]] + min == #2[[1]])&]; len = Map[Length, tmp]; pos = Flatten[Position[len, Max[len], Infinity, 1]][[1]]; tmp[[pos]] ] SGKernel[left_?NonNegative, right_?NonNegative, degree_?NonNegative, derivative_?NonNegative] := Module[{i, j, k, l, matrix, vector}, matrix = Table[ (* matrix is symmetric *) l = i + j; If[l == 0, left + right + 1, (*Else*) Sum[k^l, {k, -left, right}] ], {i, 0, degree}, {j, 0, degree} ]; vector = LinearSolve[ matrix, MapAt[1&, Table[0, {degree+1}], derivative+1] ]; (* vector = Inverse[matrix][[derivative + 1]]; *) Table[ vector.Table[If[i == 0, 1, k^i], {i, 0, degree}], {k, -left, right} ] ] /; derivative <= degree <= left+right Smooth[list_?MatrixQ, window_, degree_, derivative_:0]:= Module[{kernel, list1, list2, margin, space}, margin = Floor[window/2]; list1 = Take[ Map[First, list], {margin + 1, Length[list] - margin} ]; list2 = Map[Last, list]; kernel = SGKernel[margin, margin, degree, derivative]; list2 = ListCorrelate[kernel, list2]; (* Data _should_ be equally spaced, but... *) space = Min[Drop[list1, 1] - Drop[list1, -1]]; list2 = list2*(derivative!/space^derivative); Transpose[{list1, list2}] ] /; derivative <= degree <= 2*Floor[window/2] && $VersionNumber >= 4.0 Smooth[list_?VectorQ, window_, degree_, derivative_:0]:= Module[{pairs}, pairs = MapThread[List, {Range[Length[list]], list}]; Map[Last, Smooth[pairs, window, degree, derivative]] ] SmoothAll[{x_?VectorQ, y_?MatrixQ}, window_, degree_, derivative_:0]:= Module[{old, new, tmp}, tmp = Map[( old = Transpose[{x, #}]; new = Smooth[old, window, degree, derivative]; Map[Last, new])&, y ]; {Map[First, new], tmp} ] Scan[Protect, definitions] End[] EndPackage[]
cm^-1, but you actually need the spectrum innm. Describe the specific applications and also the sampling rate as there are parameters that depend on it. Also have you considered using other tools to smooth your data ? $\endgroup$the m-file can not be downloadedIt worked for me, just downloaded it the m file and the .nb file. The trick is to right-click->Save Link As... and not to click on it. $\endgroup$