Преобразовать ряд значений в относительную шкалу 1-10 - PullRequest
0 голосов
/ 16 февраля 2012

Допустим, у меня есть несколько наборов значений, подобных этому:

Высота (в дюймах):

John 72.3
Peter 64.5
Frank 78.5
Susan 65.8
Judy 69.0
Mary 72.7

Вес (в фунтах):

John 212
Peter 232
Frank 140
Susan 355
Judy 105
Mary 76

Возраст (в секундах с рождения)

John 662256000
Peter 1292976000
Frank 977616000
Susan 1229904000
Judy 599184000
Mary 283824000

Как лучше всего преобразовать эти значения в шкалу 1–10 относительно других значений?

Я хочу сказать, что Джон - это 6/10 по росту, 10/10 по росту и 3/10 по возрасту (составленные значения).

Одна проблема, которую я хотел бы избежать, это то, что экстремальные значения с обеих сторон слишком сильно искажают систему. Очень тяжелый или высокий человек не должен искажать всю шкалу.

Ответы [ 4 ]

1 голос
/ 16 февраля 2012

В R вы можете использовать quantile, чтобы найти децили данных, а затем findInterval, чтобы найти интервал, в котором находится каждое наблюдение.

x <- rnorm(100)
findInterval( x, quantile(x, seq(0,1,length=11))) )
1 голос
/ 16 февраля 2012

Разве это не просто:

y = (x-min)/(max-min)*9+1

Возможно с некоторым округлением, используя

sprintf '%.0f'

use strict;
use warnings;

use List::MoreUtils qw( minmax );

my %people = (
   John  => { height => 72.3, weight => 212, age =>  662256000 },
   Peter => { height => 64.5, weight => 232, age => 1292976000 },
   Frank => { height => 78.5, weight => 140, age =>  977616000 },
   Susan => { height => 65.8, weight => 355, age => 1229904000 },
   Judy  => { height => 69.0, weight => 105, age =>  599184000 },
   Mary  => { height => 72.7, weight =>  76, age =>  283824000 },
);

sub scale {
   my ($min, $max, $x) = @_;
   return ($x-$min)/($max-$min)*9+1;
}

my ($min_height, $max_height) = minmax( map $_->{height}, values %people );
my ($min_weight, $max_weight) = minmax( map $_->{weight}, values %people );
my ($min_age,    $max_age   ) = minmax( map $_->{age   }, values %people );

for my $name (keys %people) {
   my $person = $people{$name};
   printf("%-6s  height: %2.0f/10  weight: %2.0f/10  age: %2.0f/10\n",
      "$name:",
      scale($min_height, $max_height, $person->{height}),
      scale($min_weight, $max_weight, $person->{weight}),
      scale($min_age,    $max_age,    $person->{age   }),
   );
}

Выход:

Susan:  height:  2/10  weight: 10/10  age:  9/10
John:   height:  6/10  weight:  5/10  age:  4/10
Mary:   height:  6/10  weight:  1/10  age:  1/10
Judy:   height:  4/10  weight:  2/10  age:  4/10
Peter:  height:  1/10  weight:  6/10  age: 10/10
Frank:  height: 10/10  weight:  3/10  age:  7/10
1 голос
/ 16 февраля 2012

Если вы хотите, чтобы ваш образец был равномерно распределен по каждому из ваших 1, 2, ... 10, то я предлагаю вам использовать квантили. В R:

> relative.scale <- function(x) {
+     percentiles <- quantile(x, probs = seq(0,0.9,0.1))
+     sapply(x, function(v)sum(percentiles <= v))
+ }

> x <- runif(100)
> s <- relative.scale(x)
> table(s)
s
 1  2  3  4  5  6  7  8  9 10 
10 10 10 10 10 10 10 10 10 10 
1 голос
/ 16 февраля 2012

В R

heightOrder <- order(height)

даст вам порядок ранга каждого предмета.Если их 10, то будет 1-10.Вы можете масштабировать это до 10.

heightOrder <- heightOrder / max(heightOrder) * 10

Теперь это идет от 0-10.Хотя теперь, когда я смотрю на ваш вопрос, вы задали «лучший путь».Лучший способ масштабирования зависит от того, чего вы хотите достичь.Вы должны добавить больше к своему вопросу, чтобы действительно знать лучший способ.

...