PostgreSQL suporta operador de distância
<->
e pelo que entendi, isso pode ser usado para analisar texto (com o módulo pg_trgrm) e geometria
tipo de dados. Eu não sei como você pode usá-lo com mais de 1 dimensão. Talvez você tenha que definir sua própria função de distância ou de alguma forma converter seus dados em uma coluna com texto ou tipo de geometria. Por exemplo, se você tiver uma tabela com 8 colunas (cubo de 8 dimensões):
c1 c2 c3 c4 c5 c6 c7 c8
1 0 1 0 1 0 1 2
Você pode convertê-lo para:
c1 c2 c3 c4 c5 c6 c7 c8
a b a b a b a c
E então para a tabela com uma coluna:
c1
abababac
Então você pode usar (depois de criar
gist
índice
):SELECT c1, c1 <-> 'ababab'
FROM test_trgm
ORDER BY c1 <-> 'ababab';
Exemplo
Criar dados de amostra
-- Create some temporary data
-- ! Note that table are created in tmp schema (change sql to your scheme) and deleted if exists !
drop table if exists tmp.test_data;
-- Random integer matrix 100*8
create table tmp.test_data as (
select
trunc(random()*100)::int as input_variable_1,
trunc(random()*100)::int as input_variable_2,
trunc(random()*100)::int as input_variable_3,
trunc(random()*100)::int as input_variable_4,
trunc(random()*100)::int as input_variable_5,
trunc(random()*100)::int as input_variable_6,
trunc(random()*100)::int as input_variable_7,
trunc(random()*100)::int as input_variable_8
from
generate_series(1,100,1)
);
Transforme dados de entrada em texto
drop table if exists tmp.test_data_trans;
create table tmp.test_data_trans as (
select
input_variable_1 || ';' ||
input_variable_2 || ';' ||
input_variable_3 || ';' ||
input_variable_4 || ';' ||
input_variable_5 || ';' ||
input_variable_6 || ';' ||
input_variable_7 || ';' ||
input_variable_8 as trans_variable
from
tmp.test_data
);
Isso lhe dará uma variável
trans_variable
onde todas as 8 dimensões são armazenadas:trans_variable
40;88;68;29;19;54;40;90
80;49;56;57;42;36;50;68
29;13;63;33;0;18;52;77
44;68;18;81;28;24;20;89
80;62;20;49;4;87;54;18
35;37;32;25;8;13;42;54
8;58;3;42;37;1;41;49
70;1;28;18;47;78;8;17
Em vez de
||
operador você também pode usar a seguinte sintaxe (mais curta, mas mais enigmática):select
array_to_string(string_to_array(t.*::text,''),'') as trans_variable
from
tmp.test_data t
Adicionar índice
create index test_data_gist_index on tmp.test_data_trans using gist(trans_variable);
Test distanceNote:selecionei uma linha da tabela -
52;42;18;50;68;29;8;55
- e usou um valor ligeiramente alterado (42;42;18;52;98;29;8;55
) para testar a distância. Claro, você terá valores completamente diferentes em seus dados de teste, porque é uma matriz RANDOM. select
*,
trans_variable <-> '42;42;18;52;98;29;8;55' as distance,
similarity(trans_variable, '42;42;18;52;98;29;8;55') as similarity,
from
tmp.test_data_trans
order by
trans_variable <-> '52;42;18;50;68;29;8;55';
Você pode usar o operador de distância <-> ou a função de similaridade. Distância =1 - Semelhança