I1M2014: Estadística descriptiva en Haskell
En la segunda parte de la clase de hoy de Informática de 1º del Grado en Matemáticas hemos comentado las soluciones a los ejercicios de la relación 33 sobre estadística descriptiva.
Los ejercicios y su solución se muestran a continuación
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
-- --------------------------------------------------------------------- -- Introducción -- -- --------------------------------------------------------------------- -- El objetivo de esta relación es definir las principales medidas -- estadísticas de centralización (medias, mediana y modas) y de -- dispersión (rango, desviación media, varianza y desviación típica) -- que se estudian en 3º de ESO (como en http://bit.ly/1yXc7mv ). -- --------------------------------------------------------------------- -- Librerías auxiliares -- -- --------------------------------------------------------------------- import Data.List import Data.Map (Map) import qualified Data.Map as M import Test.QuickCheck -- --------------------------------------------------------------------- -- Medidas de centralización -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 1. Definir la función -- media :: Floating a => [a] -> a -- tal que (media xs) es la media aritmética de los números de la lista -- xs. Por ejemplo, -- media [4,8,4,5,9] == 6.0 -- --------------------------------------------------------------------- media :: Floating a => [a] -> a media xs = sum xs / genericLength xs -- --------------------------------------------------------------------- -- Ejercicio 2. La mediana de una lista de valores es el valor de -- la lista que ocupa el lugar central de los valores ordenados de menor -- a mayor. Si el número de datos es impar se toma como valor de la -- mediana el valor central. Si el número de datos es par se toma como -- valor de la mediana la media aritmética de los dos valores -- centrales. -- -- Definir la función -- mediana :: (Floating a, Ord a) => [a] -> a -- tal que (mediana xs) es la mediana de la lista xs. Por ejemplo, -- mediana [2,3,6,8,9] == 6.0 -- mediana [2,3,4,6,8,9] == 5.0 -- mediana [9,6,8,4,3,2] == 5.0 -- --------------------------------------------------------------------- mediana :: (Floating a, Ord a) => [a] -> a mediana xs | odd n = head $ drop (n `div` 2) ys | even n = media $ take 2 $ drop i ys where ys = sort xs n = length xs i = (n `div` 2) - 1 -- --------------------------------------------------------------------- -- Ejercicio 3. Comprobar con QuickCheck que para cualquier lista no -- vacía xs el número de elementos de xs menores que su median es menor -- o igual que la mitad de los elementos de xs y lo mismo pasa con los -- mayores o iguales que la mediana. -- --------------------------------------------------------------------- -- La propiedad es prop_mediana :: (Floating a, Ord a) => [a] -> Property prop_mediana xs = not (null xs) ==> genericLength [x | x <- xs, x < m] <= n/2 && genericLength [x | x <- xs, x > m] <= n/2 where m = mediana xs n = genericLength xs -- La comprobación es -- ghci> quickCheck prop_mediana -- +++ OK, passed 100 tests. -- --------------------------------------------------------------------- -- Ejercicio 4. Definir la función -- frecuenciasD :: Ord a => [a] -> Map a Int -- tal que (frecuenciasD xs) es el diccionario formado por los elementos -- de xs junto con el número de veces que aparecen en xs. Por ejemplo, -- frecuenciasD "sosos" == M.fromList [('o',2),('s',3)] -- frecuenciasD (show (10^100)) == M.fromList [('0',100),('1',1)] -- --------------------------------------------------------------------- -- 1ª definición (por recursión): frecuenciasD1 :: Ord a => [a] -> Map a Int frecuenciasD1 [] = M.empty frecuenciasD1 (x:xs) = M.insertWith (+) x 1 (frecuenciasD1 xs) -- 2ª definición (por plegado) frecuenciasD2 :: Ord a => [a] -> Map a Int frecuenciasD2 = foldl' (\d x-> M.insertWith' (+) x 1 d) M.empty -- Comparación de eficiencia -- ghci> frecuenciasD1 (take (10^6) (cycle "abc")) -- fromList [('a',333334),('b',333333),('c',333333)] -- (3.85 secs, 479811608 bytes) -- ghci> frecuenciasD2 (take (10^6) (cycle "abc")) -- fromList [('a',333334),('b',333333),('c',333333)] -- (0.72 secs, 218612192 bytes) -- -- ghci> size (frecuenciasD1 (take (10^6) (cycle [1..10^6]))) -- 1000000 -- (11.35 secs, 2435622280 bytes) -- ghci> size (frecuenciasD2 (take (10^6) (cycle [1..10^6]))) -- 1000000 -- (2.83 secs, 1621887768 bytes) -- En lo sucesivo, usaremos la 2ª definición: frecuenciasD :: Ord a => [a] -> Map a Int frecuenciasD = frecuenciasD2 -- --------------------------------------------------------------------- -- Ejercicio 5. Definir la función -- frecuencias :: Ord a => [a] -> [(a,Int)] -- tal que (frecuencias xs) es la lista formada por los elementos de xs -- junto con el número de veces que aparecen en xs. Por ejemplo, -- frecuencias "sosos" == [('o',2),('s',3)] -- frecuencias (show (10^100)) == [('0',100),('1',1)] -- --------------------------------------------------------------------- -- 1ª definición (usando frecuenciasD): frecuencias1 :: Ord a => [a] -> [(a,Int)] frecuencias1 = M.toList . frecuenciasD -- 2ª definición (sin usar frecuenciasD): frecuencias2 :: Ord a => [a] -> [(a,Int)] frecuencias2 xs = [(x,1 + length xs) | (x:xs) <- group (sort xs)] -- En lo sucesivo usaremos la 1ª definición frecuencias :: Ord a => [a] -> [(a,Int)] frecuencias = frecuencias1 -- --------------------------------------------------------------------- -- Ejercicio 6. Las modas de una lista son los elementos de la lista -- que más se repiten. -- -- Definir la función -- modas :: Ord a => [a] -> [a] -- tal que (modas xs) es la lista ordenada de las modas de xs. Por -- ejemplo -- modas [7,3,7,5,3,1,6,9,6] == [3,6,7] -- --------------------------------------------------------------------- -- 1ª definición (con frecuenciasD): modas1 :: Ord a => [a] -> [a] modas1 xs = M.keys (M.filter (==m) d) where d = frecuenciasD xs m = maximum (M.elems d) -- 2ª definición (con frecuencias): modas2 :: Ord a => [a] -> [a] modas2 xs = [y | (y,n) <- ys, n == m] where ys = frecuencias xs m = maximum (map snd ys) -- Comparación de eficiencia: -- ghci> modas1 (1:[1..10^6]) -- [1] -- (3.83 secs, 1638455984 bytes) -- ghci> modas2 (1:[1..10^6]) -- [1] -- (4.72 secs, 1798442320 bytes) -- En lo que sigue usaremos la 1ª definición modas :: Ord a => [a] -> [a] modas = modas1 -- --------------------------------------------------------------------- -- Ejercicio 7. La media geométrica de una lista de n números es la -- raíz n-ésima del producto de todos los números. -- -- Definir la función -- mediaGeometrica :: Floating a => [a] -> a -- tal que (mediaGeometrica xs) es la media geométrica de xs. Por -- ejemplo, -- mediaGeometrica [2,18] == 6.0 -- mediaGeometrica [3,1,9] == 3.0 -- --------------------------------------------------------------------- mediaGeometrica :: Floating a => [a] -> a mediaGeometrica xs = (product xs)**(1 / genericLength xs) -- --------------------------------------------------------------------- -- Ejercicio 8. Comprobar con QuickCheck que la media geométrica de -- cualquier lista no vacía de números no negativos es siempre menor o -- igual que la media aritmética. -- --------------------------------------------------------------------- -- La propiedad es prop_mediaGeometrica :: (Floating a, Ord a) => [a] -> Property prop_mediaGeometrica xs = not (null xs) ==> mediaGeometrica ys <= media ys where ys = map abs xs -- La comprobación es -- ghci> quickCheck prop_mediaGeometrica -- +++ OK, passed 100 tests. -- --------------------------------------------------------------------- -- Medidas de dispersión -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 9. El recorrido (o rango) de una lista de valores es la -- diferencia entre el mayor y el menor. -- -- Definir la función -- rango :: (Num a, Ord a) => [a] -> a -- tal que (rango xs) es el rango de xs. Por ejemplo, -- rango [4,2,4,7,3] == 5 -- --------------------------------------------------------------------- rango :: (Num a, Ord a) => [a] -> a rango xs = maximum xs - minimum xs -- --------------------------------------------------------------------- -- Ejercicio 10. La desviación media de una lista de datos xs es la -- media de las distancias de los datos a la media xs, donde la -- distancia entre dos elementos es el valor absoluto de su -- diferencia. Por ejemplo, la desviación media de [4,8,4,5,9] es 2 ya -- que la media de [4,8,4,5,9] es 6 y -- (|4-6| + |8-6| + |4-6| + |5-6| + |9-6|) / 5 -- = (2 + 2 + 2 + 1 + 3) / 5 -- = 2 -- -- Definir la función -- desviacionMedia :: Floating a => [a] -> a -- tal que (desviacionMedia xs) es la desviación media de xs. Por -- ejemplo, -- desviacionMedia [4,8,4,5,9] == 2.0 -- desviacionMedia (replicate 10 3) == 0.0 -- --------------------------------------------------------------------- desviacionMedia :: Floating a => [a] -> a desviacionMedia xs = media $ map (\x -> abs(x - m)) xs where m = media xs -- --------------------------------------------------------------------- -- Ejercicio 11. La varianza de una lista datos es la media de los -- cuadrados de las distancias de los datos a la media. Por ejemplo, la -- varianza de [4,8,4,5,9] es 4.4 ya que la media de [4,8,4,5,9] es 6 y -- ((4-6)^2 + (8-6)^2 + (4-6)^2 + (5-6)^2 + (9-6)^2) / 5 -- = (4 + 4 + 4 + 1 + 9) / 5 -- = 4.4 -- -- Definir la función -- varianza :: Floating a => [a] -> a -- tal que (desviacionMedia xs) es la varianza de xs. Por ejemplo, -- varianza [4,8,4,5,9] == 4.4 -- varianza (replicate 10 3) == 0.0 -- --------------------------------------------------------------------- varianza :: Floating a => [a] -> a varianza xs = media $ map (\x -> (x - m)^2) xs where m = media xs -- --------------------------------------------------------------------- -- Ejercicio 12. La desviación típica de una lista de datos es la raíz -- cuadrada de su varianza. -- -- Definir la función -- desviacionTipica :: Floating a => [a] -> a -- tal que (desviacionTipica xs) es la desviación típica de xs. Por -- ejemplo, -- desviacionTipica [4,8,4,5,9] == 2.0976176963403033 -- desviacionTipica (replicate 10 3) == 0.0 -- --------------------------------------------------------------------- desviacionTipica :: Floating a => [a] -> a desviacionTipica = sqrt . varianza |