Padronizar as amostras (calcular o z-score)


14

Dada uma lista de números de ponto flutuante, padronize-a .

Detalhes

  • Uma lista x1,x2,,xn é padronizada se a média de todos os valores for 0 e o desvio padrão for 1. Uma maneira de calcular isso é calculando primeiro a média μ e o desvio padrão σ como e depois computando a padronização substituindo cada por .
    μ=1ni=1nxiσ=1ni=1n(xiμ)2,
    xixiμσ
  • Você pode supor que a entrada contenha pelo menos duas entradas distintas (o que implica ).σ0
  • Observe que algumas implementações usam o desvio padrão da amostra, que não é igual ao desvio padrão da população que estamos usando aqui.σ
  • Existe uma resposta CW para todas as soluções triviais .

Exemplos

[1,2,3] -> [-1.224744871391589,0.0,1.224744871391589]
[1,2] -> [-1,1]
[-3,1,4,1,5] -> [-1.6428571428571428,-0.21428571428571433,0.8571428571428572,-0.21428571428571433,1.2142857142857144]

(Estes exemplos foram gerados com este script .)

Respostas:





4

MATL , 10 bytes

tYm-t&1Zs/

Experimente online!

Explicação

t       % Implicit input
        % Duplicate
Ym      % Mean
-       % Subtract, element-wise
t       % Duplicate
&1Zs    % Standard deviation using normalization by n
/       % Divide, element-wise
        % Implicit display

4

APL + WIN, 41,32 30 bytes

9 bytes salvos graças a Erik e mais 2 graças a ngn

x←v-(+/v)÷⍴v←⎕⋄x÷(+/x×x÷⍴v)*.5

Solicita o vetor de números e calcula o desvio padrão médio e os elementos padronizados do vetor de entrada


Você não pode atribuir x←v-(+/v)÷⍴v←⎕e depois atribuir x÷((+/x*2)÷⍴v)*.5?
Erik the Outgolfer

Eu posso mesmo. Obrigado.
Graham

apl + win do extensão singleton ( 1 2 3+,4← → 1 2 3+4)? se sim, você pode reescrever (+/x*2)÷⍴vcomo+/x×x÷⍴v
ngn

@ngn Isso funciona por mais 2 bytes. Obrigado.
Graham

3

R + pryr, 53 52 bytes

-1 byte usando em sum(x|1)vez de length(x)como visto na solução de @Robert S.

pryr::f((x-(y<-mean(x)))/(sum((x-y)^2)/sum(x|1))^.5)

Por ser uma linguagem criada para estatísticos, estou surpreso que isso não tenha uma função interna. Pelo menos não um que eu pudesse encontrar. Mesmo a função mosaic::zscorenão produz os resultados esperados. Provavelmente, isso se deve ao uso do desvio padrão da população em vez do desvio padrão da amostra.

Experimente online!


2
Você pode mudar <-para um =para economizar 1 byte.
Robert S.

@ J.Doe não, usei o método que comentei na solução de Robert S. scaleé legal!
21718 Giuseppe

2
@ J.Doe desde que você só usar numa vez que você pode usá-lo diretamente para 38 bytes
Giuseppe

2
@RobertS. aqui no PPCG, tendemos a incentivar a permissão de entrada e saída flexíveis, incluindo a saída de mais do que o necessário, com exceção dos desafios em que o layout preciso da saída é o ponto principal do desafio.
ngm

6
É claro que R built-ins não usariam "variação de população". Apenas engenheiros confundidas usaria uma coisa dessas (hencethe Python e Matlab respostas;))
ngm

3

Tcl , 126 bytes

proc S L {lmap c $L {expr ($c-[set m ([join $L +])/[set n [llength $L]].])/sqrt(([join [lmap c $L {expr ($c-$m)**2}] +])/$n)}}

Experimente online!


2

Gelatina , 10 bytes

_ÆmµL½÷ÆḊ×

Experimente online!

Não é mais curto, mas a função determinante de Jelly ÆḊtambém calcula a norma vetorial.

_Æm             x - mean(x)
   µ            then:
    L½          Square root of the Length
      ÷ÆḊ       divided by the norm
         ×      Multiply by that value

Ei, boa alternativa! Infelizmente, não vejo uma maneira de reduzi-lo.
Erik the Outgolfer

2

Mathematica, 25 bytes

Mean[(a=#-Mean@#)a]^-.5a&

Função pura. Pega uma lista de números como entrada e retorna uma lista de números de precisão da máquina como saída. Observe que a Standardizefunção interna usa a variação de amostra por padrão.


2

J , 22 bytes

-1 byte graças ao vacas charlatão!

(-%[:%:1#.-*-%#@[)+/%#

Experimente online!

J , 31 23 bytes

(-%[:%:#@[%~1#.-*-)+/%#

Experimente online!

                   +/%# - mean (sum (+/) divided (%) by the number of samples (#)) 
(                 )     - the list is a left argument here (we have a hook)
                 -      - the difference between each sample and the mean
                *       - multiplied by 
               -        - the difference between each sample and the mean
            1#.         - sum by base-1 conversion
          %~            - divided by
       #@[              - the length of the samples list
     %:                 - square root
   [:                   - convert to a fork (function composition) 
 -                      - subtract the mean from each sample
  %                     - and divide it by sigma

1
Reorganizá-lo fornece 22 [:(%[:%:1#.*:%#)]-+/%# tio.run/##y/qfVmyrp2CgYKVg8D/… , acho que um desses limites pode ser removido, mas ainda não teve nenhuma sorte até agora, EDIT: um comportamento de bytes mais direto (-%[:%:1#.-*-%#@[)+/%#também está em 22
Kritixi Lithos

@ Vacas charlatão Obrigado!
Galen Ivanov

2

APL (Dyalog Unicode) , 33 29 bytes

{d÷.5*⍨l÷⍨+/×⍨d←⍵-(+/⍵)÷l←≢⍵}

-4 bytes graças a @ngn

Experimente online!


você pode atribuir ⍵-ma uma variável e remover m←assim:{d÷.5*⍨l÷⍨+/×⍨d←⍵-(+/⍵)÷l←≢⍵}
ngn

@ngn Ah, bom, obrigado, eu não vi que a duplicação de alguma forma
Quintec

2

Haskell, 80 75 68 bytes

t x=k(/sqrt(f$sum$k(^2)))where k g=g.(-f(sum x)+)<$>x;f=(/sum(1<$x))

Agradecemos a @flawr pelas sugestões de uso, em sum(1<$x)vez de sum[1|_<-x]e para alinhar a média, @xnor por incluir o desvio padrão e outras reduções.

Expandido:

-- Standardize a list of values of any floating-point type.
standardize :: Floating a => [a] -> [a]
standardize input = eachLessMean (/ sqrt (overLength (sum (eachLessMean (^2)))))
  where

    -- Map a function over each element of the input, less the mean.
    eachLessMean f = map (f . subtract (overLength (sum input))) input

    -- Divide a value by the length of the input.
    overLength n = n / sum (map (const 1) input)

1
Você pode substituir [1|_<-x]por (1<$x)para salvar alguns bytes. Esse é um ótimo truque para evitar o fromIntegralque eu não vi até agora!
flawr

A propósito: eu gosto de usar a tryitonline , você pode executar seu código lá e copiar o aswer pré-formatado para postar aqui!
flawr


Você pode escrever (-x+)para (+(-x))evitar parênteses. Também parece que fpode ser sem sentido:, f=(/sum(1<$x))e spode ser substituído por sua definição.
xnor

@xnor Ooh, (-x+)é útil, tenho certeza que usarei isso no futuro
Jon Purdy

2

MathGolf , 7 bytes

▓-_²▓√/

Experimente online!

Explicação

Isso é literalmente uma recriação de byte por byte da resposta 05AB1E de Kevin Cruijssen, mas economizo alguns bytes do MathGolf com 1 byters para tudo o que é necessário para esse desafio. Também a resposta parece muito boa na minha opinião!

▓         get average of list
 -        pop a, b : push(a-b)
  _       duplicate TOS
   ²      pop a : push(a*a)
    ▓     get average of list
     √    pop a : push(sqrt(a)), split string to list
      /   pop a, b : push(a/b), split strings

1

JavaScript (ES7),  80  79 bytes

a=>a.map(x=>(x-g(a))/g(a.map(x=>(x-m)**2))**.5,g=a=>m=eval(a.join`+`)/a.length)

Experimente online!

Comentado

a =>                      // given the input array a[]
  a.map(x =>              // for each value x in a[]:
    (x - g(a)) /          //   compute (x - mean(a)) divided by
    g(                    //   the standard deviation:
      a.map(x =>          //     for each value x in a[]:
        (x - m) ** 2      //       compute (x - mean(a))²
      )                   //     compute the mean of this array
    ) ** .5,              //   and take the square root
    g = a =>              //   g = helper function taking an array a[],
      m = eval(a.join`+`) //     computing the mean
          / a.length      //     and storing the result in m
  )                       // end of outer map()


1

Haskell , 59 bytes

(%)i=sum.map(^i)
f l=[(0%l*y-1%l)/sqrt(2%l*0%l-1%l^2)|y<-l]

Experimente online!

Não usa bibliotecas.

A função auxiliar %calcula a soma dos ith poderes de uma lista, o que nos permite obter três valores úteis.

  • 0%l é o comprimento de l (chame isso n)
  • 1%lé a soma de l(chame issos )
  • 2%lé a soma dos quadrados de l(chame isso m)

Podemos expressar o escore z de um elemento ycomo

(n*y-s)/sqrt(n*v-s^2)

(Essa é a expressão (y-s/n)/sqrt(v/n-(s/n)^2)simplificada um pouco, multiplicando a parte superior e inferior porn .)

Podemos inserir as expressões 0%l, 1%l, 2%lsem parênteses porque o% definimos tem precedência maior do que os operadores aritméticos.

(%)i=sum.map(^i)tem o mesmo comprimento que i%l=sum.map(^i)l. Torná-lo mais livre de pontos não ajuda. Defini-lo como g i=...perde bytes quando o chamamos. Embora %funcione para qualquer lista, mas só a chamamos com a lista de entrada do problema, não há perda de bytes em chamá-la com argumento ltodas as vezes, porque uma chamada de dois argumentos i%lnão é maior que a de um argumento g i.


Nós temos euUMATEX aqui:)
flawr

Eu realmente gosto da %ideia! Parece com a versão discreta dos momentos estatísticos .
flawr

1

K (ok) , 33 23 bytes

-10 bytes graças a ngn!

{t%%(+/t*t:x-/x%#x)%#x}

Experimente online!

Primeira tentativa de codificação (não me atrevo a chamá-lo de "golfe") em K. Tenho certeza de que isso pode ser feito muito melhor (muitos nomes de variáveis ​​aqui ...)


1
legais! você pode substituir a inicial (x-m)por t( tio )
NGN

1
o interno { }é desnecessário - seu nome implícito de parâmetro é xe foi passado xcomo argumento ( tio )
ngn

1
outro -1 byte substituindo x-+/xpor x-/x. o argumento esquerdo -/serve como valor inicial para a redução ( tio )
ngn

@ngn Obrigado! Agora vejo que os 2 primeiros golfe são óbvios; o último está além do meu nível atual :)
Galen Ivanov


1

TI-Basic (série 83), 14 11 bytes

Ans-mean(Ans
Ans/√(mean(Ans²

Recebe entrada Ans. Por exemplo, se você digitar o item acima prgmSTANDARD, {1,2,3}:prgmSTANDARDretornará {-1.224744871,0.0,1.224744871}.

Anteriormente, tentei usar o 1-Var Statscomando, que armazena o desvio padrão da população σx, mas é menos complicado calculá-lo manualmente.


1

05AB1E , 9 bytes

ÅA-DnÅAt/

Porta da resposta JavaScript de @Arnauld , certifique-se de vomitá-lo!

Experimente online ou verifique todos os casos de teste .

Explicação:

ÅA          # Calculate the mean of the (implicit) input
            #  i.e. [-3,1,4,1,5] → 1.6
  -         # Subtract it from each value in the (implicit) input
            #  i.e. [-3,1,4,1,5] and 1.6 → [-4.6,-0.6,2.4,-0.6,3.4]
   D        # Duplicate that list
    n       # Take the square of each
            #  i.e. [-4.6,-0.6,2.4,-0.6,3.4] → [21.16,0.36,5.76,0.36,11.56]
     ÅA     # Pop and calculate the mean of that list
            #  i.e. [21.16,0.36,5.76,0.36,11.56] → 7.84
       t    # Take the square-root of that
            #  i.e. 7.84 → 2.8
        /   # And divide each value in the duplicated list with it (and output implicitly)
            #  i.e. [-4.6,-0.6,2.4,-0.6,3.4] and 2.8 → [-1.6428571428571428,
            #   -0.21428571428571433,0.8571428571428572,-0.21428571428571433,1.2142857142857144]


0

Pyth, 21 19 bytes

mc-dJ.OQ@.Om^-Jk2Q2

Experimente online aqui .

mc-dJ.OQ@.Om^-Jk2Q2Q   Implicit: Q=eval(input())
                       Trailing Q inferred
    J.OQ               Take the average of Q, store the result in J
           m     Q     Map the elements of Q, as k, using:
             -Jk         Difference between J and k
            ^   2        Square it
         .O            Find the average of the result of the map
        @         2    Square root it
                       - this is the standard deviation of Q
m                  Q   Map elements of Q, as d, using:
  -dJ                    d - J
 c                       Float division by the standard deviation
                       Implicit print result of map

Editar: depois de ver a resposta de Kevin , alterado para usar a média incorporada para os resultados internos. Resposta anterior:mc-dJ.OQ@csm^-Jk2QlQ2


0

SNOBOL4 (CSNOBOL4) , 229 bytes

	DEFINE('Z(A)')
Z	X =X + 1
	M =M + A<X>	:S(Z)
	N =X - 1.
	M =M / N
D	X =GT(X) X - 1	:F(S)
	A<X> =A<X> - M	:(D)
S	X =LT(X,N) X + 1	:F(Y)
	S =S + A<X> ^ 2 / N	:(S)
Y	S =S ^ 0.5
N	A<X> =A<X> / S
	X =GT(X) X - 1	:S(N)
	Z =A	:(RETURN)

Experimente online!

Link é para uma versão funcional do código que constrói uma matriz a partir de STDIN, dado seu comprimento e seus elementos, e então executa a função Z e, finalmente, imprime os valores.

Define uma função Z que retorna uma matriz.

A 1.linha 4 é necessária para fazer a aritmética do ponto flutuante corretamente.



0

Carvão , 25 19 bytes

≧⁻∕ΣθLθθI∕θ₂∕ΣXθ²Lθ

Experimente online! Link é a versão detalhada do código. Explicação:

       θ    Input array
≧           Update each element
 ⁻          Subtract
   Σ        Sum of
    θ       Input array
  ∕         Divided by
     L      Length of
      θ     Input array

Calcular μ e vetorizado subtraí-lo de cada xEu.

  θ         Updated array
 ∕          Vectorised divided by
   ₂        Square root of
     Σ      Sum of
       θ    Updated array
      X     Vectorised to power
        ²   Literal 2
    ∕       Divided by
         L  Length of
          θ Array
I           Cast to string
            Implicitly print each element on its own line.

Calcular σ, vetorizados dividem cada xEu por ele e produz o resultado.

Edit: salvou 6 bytes graças a @ ASCII-only para a) usar em SquareRoot()vez de Power(0.5)b) consertar vetorizado Divide()(estava fazendo isso IntDivide()) c) fazer Power()vetorizar.


riscado 25 = sem bytes? : P (Além disso, você ainda não atualizou o link do TIO)
somente ASCII

@ Somente ASCII Opa, obrigado!
Neil
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.