簡體   English   中英

從SQLite數據庫檢索和繪制有序的2D熱圖數據

[英]Retrieving and plotting ordered, 2D heatmap data from a SQLite database

我本周大部分時間都在努力應對,我認為我最有可能在這里尋求幫助。 我將2D數組數據存儲在SQLite數據庫中,我希望對其進行獲取和可視化。 盡管我不確定如何處理,但對於我需要如何獲取和繪制數據有很多限制。

因此,我有一個數據庫,其中的表包含如下內容:

| ID | SourceID | TargetID | Parameter | Values  |
| 1  |    21    |    34    | 23.46513  | 0.12654 |
| 2  |    21    |    34    | 23.46513  | 0.25478 |
| 3  |    21    |    46    | 23.46513  | 0.43564 |
| 4  |    21    |    46    | 23.46513  | 1.02487 |
| 5  |    34    |    21    | 14.56319  | 0.01476 |
| 6  |    34    |    21    | 14.56319  | 0.87265 |
| 7  |    34    |    46    | 14.56319  | 0.46478 |
| 8  |    34    |    46    | 14.56319  | 0.13665 |
| 9  |    46    |    21    | 7.99581   | 0.04189 |
| 10 |    46    |    21    | 7.99581   | 0.91754 |
| 11 |    46    |    34    | 7.99581   | 0.73688 |
| 12 |    46    |    34    | 7.99581   | 0.24299 |

該數據集的一些功能需要注意:

  • ID是關鍵,並且是唯一的
  • SourceIDTargetID值來自同一組。 在這種情況下,它們都包含{21,34,46}。 SourceID列構成熱圖的x軸數據,而TargetID列構成y軸數據。
  • Values列包含必須在熱圖中繪制的數據。
  • Parameter列是我需要用來對數據進行排序的列,因為我需要創建一個有序的熱圖。 在這種情況下, Parameter基於與每個SourceIDTargetID關聯的值。

下表顯示了每個SourceId / TargetId與一個Parameter值的關聯:

| SourceID/TargetID | Parameter |
|       46          | 7.99581   |
|       34          | 14.56319  |
|       21          | 23.46513  |

基於我提出的另一個問題 ,我知道我可以使用SQL查詢根據以下Values的最小值將表簡化為( SourceIdTargetId )的唯一組合:

SELECT SourceID, TargetID, min(Values)
  FROM dataset
  GROUP BY SourceID, TargetID;

這將產生以下簡化表:

| ID | SourceID | TargetID | SourceSort | Values  |
| 1  |    21    |    34    |  23.46513  | 0.12654 |
| 3  |    21    |    46    |  23.46513  | 0.43564 |
| 5  |    34    |    21    |  14.56319  | 0.01476 |
| 8  |    34    |    46    |  14.56319  | 0.13665 |
| 9  |    46    |    21    |  7.99581   | 0.04189 |
| 12 |    46    |    34    |  7.99581   | 0.24299 |

我苦苦掙扎的一點是,我現在需要根據Parameter的值對該表進行排序。 如果我在SQL查詢中添加ORDER BY Parameter ,它會成功排序SourceID列,但對於具有相同SourceID行, TargetID列不會根據此排序。 簡而言之,我想獲取下表:

| ID | SourceID | TargetID | Values  |
| 12 |    46    |    34    | 0.24299 |
| 9  |    46    |    21    | 0.04189 |    
| 8  |    34    |    46    | 0.13665 |        
| 5  |    34    |    21    | 0.01476 |
| 3  |    21    |    46    | 0.43564 |
| 1  |    21    |    34    | 0.12654 |

排序基礎的一個示例:首先根據表使用Parameter值對SourceID排序。 隨后, TargetID是基於排序Parameter排序,對其中的行SourceID值相等,例如,第1行( ID=8 )的第2行之前排序( ID=5 ),因為TargetID = 46之前,應進行排序TargetID = 21基於在相關的Parameter值上。

最后,使用此表,我需要構造一個熱圖:

(TargetID ordered by `Parameter ASC`)
 ^
 |
 | 
----------------------------------
21 | 0.04189 | 0.01476 |    0    |
----------------------------------
34 | 0.24299 |    0    | 0.12654 |
----------------------------------
46 |    0    | 0.13665 | 0.43564 |
----------------------------------
   |    46   |    34   |    21  --> (SourceID ordered by `Parameter ASC`)

為此,我正在使用Python Pandas庫,並使用read_sql()函數執行SQL查詢。 我發現我可以使用matplotlibpcolor()函數繪制熱圖。 我想使用色圖在2D數組中繪制值,並且我希望數據集的排序與上面完全一樣。 最后,我想將SourceIDTargetID值繪制為刻度標簽。

這似乎應該可行,但是到目前為止,我只能夠生成熱圖,而無需根據Parameter進行排序。 我不知道如果我占盡直接解決了排序位的SQL語句,或者我應該只是獲取數據,然后進行排序的DataFrame由返回read_sql()

無論如何,我將不勝感激! 如果有任何不清楚的地方,請讓我知道,我會盡力澄清。

謝謝!

您的sqlite表格式不正確,因為Parameter值僅反映Parameter與SourceID的關聯,而不反映TargetID。

最好有兩個表:

id_param

id  parameter
21   23.46513
34   14.56319
46    7.99581

數據集 -請注意,這里沒有“參數”列:

ID  SourceID  TargetID   Values
 1        21        34  0.12654
 2        21        34  0.25478
 3        21        46  0.43564
 4        21        46  1.02487
 5        34        21  0.01476
 6        34        21  0.87265
 7        34        46  0.46478
 8        34        46  0.13665
 9        46        21  0.04189
10        46        21  0.91754
11        46        34  0.73688
12        46        34  0.24299

那么您可以使用JOIN在SourceID / Parameter和TargetID / Parameter之間形成所需的關聯:

    SELECT d.SourceID, d.TargetID, min(d.`Values`) as min_value
      FROM dataset d
      JOIN id_param as ip1
      ON d.SourceID = ip1.id
      JOIN id_param as ip2
      ON d.TargetID = ip2.id
      GROUP BY SourceID, TargetID
      ORDER BY ip1.parameter ASC, ip2.parameter ASC

例如,

import io
import sqlite3
import pandas as pd
import matplotlib.pyplot as plt

text = '''\
| ID | SourceID | TargetID | Parameter | Values  |
| 1  |    21    |    34    | 23.46513  | 0.12654 |
| 2  |    21    |    34    | 23.46513  | 0.25478 |
| 3  |    21    |    46    | 23.46513  | 0.43564 |
| 4  |    21    |    46    | 23.46513  | 1.02487 |
| 5  |    34    |    21    | 14.56319  | 0.01476 |
| 6  |    34    |    21    | 14.56319  | 0.87265 |
| 7  |    34    |    46    | 14.56319  | 0.46478 |
| 8  |    34    |    46    | 14.56319  | 0.13665 |
| 9  |    46    |    21    | 7.99581   | 0.04189 |
| 10 |    46    |    21    | 7.99581   | 0.91754 |
| 11 |    46    |    34    | 7.99581   | 0.73688 |
| 12 |    46    |    34    | 7.99581   | 0.24299 |'''

def make_table(filename):
    # make sqlite table
    with sqlite3.connect(filename) as con:
        df = pd.read_table(io.BytesIO(text), sep=r'\s*[|]\s*').iloc[:, 1:-1]
        df.to_sql('dataset', con=con, if_exists='replace')


filename = '/tmp/data.sqlite'
make_table(filename)

with sqlite3.connect(filename) as con:
    con.execute('DROP TABLE id_param')

    sql = '''CREATE TABLE id_param 
             (id INTEGER PRIMARY KEY, parameter INTEGER)'''
    con.execute(sql)

    sql = '''INSERT INTO id_param
             SELECT SourceID, Parameter
             FROM dataset
             GROUP BY SourceID'''
    con.execute(sql)

    sql = '''
        SELECT d.SourceID, d.TargetID, min(d.`Values`) as min_value
          FROM dataset d
          JOIN id_param as ip1
          ON d.SourceID = ip1.id
          JOIN id_param as ip2
          ON d.TargetID = ip2.id
          GROUP BY SourceID, TargetID
          ORDER BY ip1.parameter ASC, ip2.parameter ASC
    '''
    df = pd.read_sql(sql, con)
    print(df)

產量

   SourceID  TargetID  min_value
0        46        34    0.24299
1        46        21    0.04189
2        34        46    0.13665
3        34        21    0.01476
4        21        46    0.43564
5        21        34    0.12654

將sqlite表轉換為Matplotlib的pcolor繪制熱圖所需的格式的最簡單方法(我看到)是使用Pandas DataFrame的pivot方法。 由於此pivot將重新排列列和行的順序,因此無需大驚小怪SQL查詢生成的順序。 相反,更容易在Pandas中修復訂單:

import io
import sqlite3
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

text = '''\
| ID | SourceID | TargetID | Parameter | Values  |
| 1  |    21    |    34    | 23.46513  | 0.12654 |
| 2  |    21    |    34    | 23.46513  | 0.25478 |
| 3  |    21    |    46    | 23.46513  | 0.43564 |
| 4  |    21    |    46    | 23.46513  | 1.02487 |
| 5  |    34    |    21    | 14.56319  | 0.01476 |
| 6  |    34    |    21    | 14.56319  | 0.87265 |
| 7  |    34    |    46    | 14.56319  | 0.46478 |
| 8  |    34    |    46    | 14.56319  | 0.13665 |
| 9  |    46    |    21    | 7.99581   | 0.04189 |
| 10 |    46    |    21    | 7.99581   | 0.91754 |
| 11 |    46    |    34    | 7.99581   | 0.73688 |
| 12 |    46    |    34    | 7.99581   | 0.24299 |'''

def make_table(filename):
    # make sqlite table
    with sqlite3.connect(filename) as con:
        df = pd.read_table(io.BytesIO(text), sep=r'\s*[|]\s*').iloc[:, 1:-1]
        df.to_sql('dataset', con=con, if_exists='replace')

filename = '/tmp/data.sqlite'
make_table(filename)

with sqlite3.connect(filename) as con:
    sql = '''
        SELECT SourceID, TargetID, min(`Values`) as min_value
          FROM dataset 
          GROUP BY SourceID, TargetID
    '''
    df = pd.read_sql(sql, con)
    table = df.pivot(index='SourceID', columns='TargetID', values='min_value')

    sql = 'SELECT DISTINCT SourceID FROM dataset ORDER BY Parameter ASC'
    order = pd.read_sql(sql, con)['SourceID']
    table = table.reindex(index=order, columns=order)

    fig, ax = plt.subplots()
    ax.pcolor(table.values, cmap=plt.get_cmap('jet'), 
              vmin=df['min_value'].min(), vmax=df['min_value'].max())
    ax.set_xticks(np.arange(table.shape[1] + 1)+0.5, minor=False)
    ax.set_xticklabels(table.columns, minor=False)
    ax.set_yticks(np.arange(table.shape[0] + 1)+0.5, minor=False)
    ax.set_yticklabels(table.index, minor=False)
    ax.set_xlim(0, table.shape[1])
    ax.set_ylim(0, table.shape[0])
    plt.show()

產量

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM