2016-01-26 6 views
1

Я пытаюсь написать функцию в clojure, чтобы найти стандартное отклонение последовательности (вектора). Пока я определил функцию, чтобы найти среднее значение набора чисел, но у меня проблема с несколькими вещами.Стандартное отклонение в clojure

Во-первых, я смущен тем, как использовать квадратный корень и полномочия в clojure. Во-вторых, я пытаюсь выяснить, как вытащить каждый элемент по отдельности из вектора и вычесть среднее из него, а затем скомпоновать его.

До сих пор это моя функция

(defn mean [a] (/ (reduce + a) (count a))) 

(defn standarddev [a] (Math/sqrt (/ (reduce + (map square #(- % (mean a) a))) (- (count a) 1)))) 

ответ

0

Сначала я запутался о том, как использовать квадратный корень и полномочия в Clojure.

Чтобы умиротворять что-то, просто умножьте его на себя:

(defn square [n] 
    (* n n)) 

Если вы хотите мощность выше, чем 2, вы можете также использовать функцию возведения в степень:

(defn exp [x n] 
    (reduce * (repeat n x))) 

Второй Я пытаюсь выяснить, как вытащить каждый элемент по отдельности из вектора и вычесть среднее из него, а затем скомпоновать его.

Clojure (функциональный) способ итерации через seq использовать map. Карта принимает функцию и коллекцию и возвращает результат применения этой функции к каждому элементу коллекции.

(defn squares [avg coll] (map #(square (- % avg)) coll)) 

Final функция стандартного отклонения, используя вышеуказанные 2 функции и ваше среднее:

(defn standard-deviation [coll] 
    (let [avg (mean coll) 
     squares (squares avg coll) 
     total (count coll)] 
    (Math/sqrt (/ (reduce + squares) (- total 1))))) 

вдохновение от: https://github.com/clojure-cookbook/clojure-cookbook/blob/master/01_primitive-data/1-20_simple-statistics.asciidoc

+0

Я думаю, У меня может быть это, но я получаю erorr, когда я пытаюсь применить свою формулу к вектору, например say (standarddev [1 2 3 4]). Что я до сих пор (defn standarddev [a] (Math/sqrt (/ (квадрат карты (карта - a (означает a))) (- (count a) 1)))) – user3483844

+0

@ user3483844 проверить свои входы на 'map', вы хотите только чтобы передать им функцию и коллекцию, вы передаете 2 коллекции (что действительно, но не то, что вы хотите сделать здесь). – Josh

+0

Итак, вот что я хочу делать. У меня есть список номеров. Сначала я хочу вычесть среднее из каждого из элементов вектора. Что я могу сделать с картой, я верю. Затем я хочу соединить каждый элемент, который я могу сделать с картой, и, наконец, я хочу добавить все квадраты, которые я могу сделать с картой. Верный? – user3483844

0

До тех пор, пока у вас есть двойной, вы можете использовать в Java Math класс (https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html) для выполнения вычислений, таких как sqrt. Вам не нужно делать что-либо особенное для доступа к классу Math, потому что Clojure делает все классы java.lang доступными для вас без импорта.

+0

Я продолжаю пытаться использовать Math.sqrt, но я получаю ошибки каждый раз, когда я пытаюсь сделать что-то простое (Math .sqrt 4) – user3483844

+1

@ user3483844 вы должны использовать 'Math/sqrt', а не' Math.sqrt' – Josh

+0

@Josh Хорошо, это сработало, спасибо. Теперь я просто должен выяснить, как перебирать список, чтобы я мог получить суммирование (x-meanx)^2 часть – user3483844

0

Вы довольно близко. Предполагая, что у вас уже есть следующие функции

(defn square [n] (* n n)) 

(defn mean [a] (/ (reduce + a) (count a))) 

2 проблемы с standarddev функции

(defn standarddev [a] (Math/sqrt (/ (map square (map - a (mean a))) (- (count a) 1)))) 

1) (map - a (mean a)) не работает, потому что вы вычитанием «число» из «вектора». Чтобы исправить повторить (mean a) столько раз, сколько элементов в «а» Самый простой и далеко не эффективным решением было бы

(map - a (repeat (mean a))) 

2) (показать на карте квадрат (карта - это (имею в виду))) Безразлично» t из-за # 1 выше и потому, что карта возвращает «вектор». Чтобы исправить просуммировать элементы вектора Теперь

(reduce + (map square (map - a (repeat (mean a))))) 

Ваша стандартная функция DEV должна быть

(defn standarddev [a] 
     (Math/sqrt (/ 
        (reduce + (map square (map - a (repeat (mean a))))) 
        (- (count a) 1)))) 
+0

Что делает часть (repeat (a))? Я тестировал его, и он работает, но что такое определение за повторением? – user3483844

+0

он просто повторяет значение, которое «(означает a)» возвращает столько раз, сколько вы хотите. Не изящное решение, а самое простое, чтобы заставить вашу работу работать. – KobbyPemson

+0

Я тестировал повтор только на своем собственном (повтор [1 2 3 4]), и он неоднократно возвращал вектор [1 2 3 4]. Как повторение (означает a) позволяет среднему отображать мою среднюю функцию на каждое значение в заданном векторе, а не бесконечно? Я просто смущен, как это работает. – user3483844

0

Вы можете немного увеличить производительность за счет избавления от map вообще

(def square #(* % %)) 

(defn standard-deviation 
    [a] 
    (let [mn (mean a)] 
    (Math/sqrt 
     (/ (reduce #(+ %1 (square (- %2 mn))) 0 a) 
     (dec (count a))))))