Reputation: 9
I have a matrix, lets use this one for example:
[ [4.0, 2.0, 0.6],
[4.2, 2.1, 0.59],
[3.9, 2.0, 0.58],
[4.3, 2.1, 0.62],
[4.1, 2.2, 0.63] ]
Now, I take the average of each column, which results in this:
[4.10, 2.08, 0.604]
All these I'm able to make, I have the informations.
What I'm having problem is at this part now. I'm looking a way to subtract each average element with his respective element on the first Matrix.
It should look like this:
[ [-0.1, -0.08, -0.004],
[0.1, 0.02, -0.014],
[-0.2, -0.08, -0.024],
[0.2, 0.02, 0.016],
[0.0, 0.12, 0.026] ]
I have to make it viable for an arbitrary-sized matrix.
Upvotes: 0
Views: 143
Reputation: 2167
Here's how I would do it:
mean l = sum l / (fromIntegral (length l))
getColumnMeans = map mean . transpose
normalizeMatrix m = map (zipWith subtract columnMeans) m
where
columnMeans = getColumnMeans m
mean
does exactly what its name suggests and getColumnMeans
is the function that you seem to have implemented yourself.
normalizeMatrix
is the function that you are looking for. It takes in a matrix, computes its column means and then subtracts it from each of its rows via map
.
subtract
function is basically (-)
but with its arguments flipped. I use it whenever I wanna map something like subtract 5
and it reads like regular English. So, subtract 5 10
would return 5
. Here, zipWith subtract columnMeans
does it on an entry-by-entry basis for a row. map
does this for all rows. Hope this is useful.
Upvotes: 1
Reputation: 67507
something like this, without validations and formatting
colmean rs = let (a,c) = agg rs in map (/(fromIntegral c)) a
agg [r] = (r,1)
agg (r:rs) = let (a,c) = agg rs in (zipWith (+) a r, c+1)
minus = flip (zipWith (-))
demean x = map (minus $ colmean x) x
> demean media
[[-9.999999999999964e-2,-8.000000000000007e-2,-4.0000000000000036e-3],
[0.10000000000000053,2.0000000000000018e-2,-1.4000000000000012e-2],
[-0.19999999999999973,-8.000000000000007e-2,-2.400000000000002e-2],
[0.20000000000000018,2.0000000000000018e-2,1.6000000000000014e-2],
[0.0,0.1200000000000001,2.6000000000000023e-2]]
with this, the second dimension (number of columns) can be infinite
> map (take 10) $ demean [[1..], [2..]]
[[-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5],
[0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5]]
Upvotes: 2