PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Postgresql k-най-близък съсед (KNN) на многомерен куб

PostgreSQL поддържа оператор за разстояние <-> и доколкото разбирам, това може да се използва за анализиране на текст (с pg_trgrm модул) и геометрия тип данни.

Не знам как можете да го използвате с повече от 1 измерение. Може би ще трябва да дефинирате своя собствена функция за разстояние или по някакъв начин да конвертирате данните си в една колона с текст или геометричен тип. Например, ако имате таблица с 8 колони (8-измерен куб):

c1 c2 c3 c4 c5 c6 c7 c8
 1  0  1  0  1  0  1  2

Можете да го конвертирате в:

c1 c2 c3 c4 c5 c6 c7 c8
 a  b  a  b  a  b  a  c

И след това към таблица с една колона:

c1
abababac

След това можете да използвате (след създаване на gist индекс ):

SELECT c1, c1 <-> 'ababab'
 FROM test_trgm 
 ORDER BY c1 <-> 'ababab';

Пример

Създайте примерни данни

-- 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)
);

Преобразувайте входните данни в текст

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
);

Това ще ви даде една променлива trans_variable където се съхраняват всичките 8 измерения:

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

Вместо || можете също да използвате следния синтаксис (по-кратък, но по-загадъчен):

select 
   array_to_string(string_to_array(t.*::text,''),'') as trans_variable
from 
   tmp.test_data t

Добавяне на индекс

create index test_data_gist_index on tmp.test_data_trans using gist(trans_variable);

Тестово разстояние Забележка:Избрах един ред от таблицата - 52;42;18;50;68;29;8;55 - и използва леко променена стойност (42;42;18;52;98;29;8;55 ), за да тествате разстоянието. Разбира се, ще имате напълно различни стойности във вашите тестови данни, защото това е СЛУЧАЙНА матрица.

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';

Можете да използвате оператор за разстояние <-> или функция за подобие. Разстояние =1 - Сходство



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Замяна на всички таблици на база данни с изключение на една с данни от друга база данни

  2. Създаване на потребител на PostgreSQL и добавянето им към база данни

  3. Sqoop на Hadoop:NoSuchMethodError:com.google.common.base.Stopwatch.createStarted()

  4. Разлика между RDBMS и ORDBMS

  5. Heroku Postgres:psql:ФАТАЛНО:няма запис в pg_hba.conf за хост