了解 Power BI 視覺效果中的資料檢視對應
本文討論資料檢視對應,並說明如何使用資料角色來建立不同類型的視覺效果。 內容說明如何指定資料角色和不同 dataMappings
類型的條件需求。
每個有效對應都會產生資料檢視。 您可以依照特定條件提供多個資料對應。 支援的對應選項如下:
"dataViewMappings": [
{
"conditions": [ ... ],
"categorical": { ... },
"single": { ... },
"table": { ... },
"matrix": { ... }
}
]
只有在 dataViewMappings
也定義了有效對應時,Power BI 才會建立資料檢視的對應。
換句話說,dataViewMappings
中可能已定義 categorical
,但未定義其他對應 (例如,table
或 single
)。 在此情況下,Power BI 會產生具有單一 categorical
對應的資料檢視,而 table
和其他對應則維持未定義。 例如:
"dataViewMappings": [
{
"categorical": {
"categories": [ ... ],
"values": [ ... ]
},
"metadata": { ... }
}
]
條件
conditions
區段會建立特定資料對應的規則。 如果資料符合其中一組描述的條件,視覺效果會接受該資料為有效資料。
您可以為每個欄位指定最小值和最大值。 該值代表可以繫結至該資料角色的欄位數目。
注意
如果條件中省略了資料角色,則可以有任意數目的欄位。
在下列範例中,category
限制使用一個資料欄位,而 measure
限制使用兩個資料欄位。
"conditions": [
{ "category": { "max": 1 }, "measure": { "max": 2 } },
]
您也可以為資料角色設定多個條件。 在此情況下,如果符合任何一個條件,則資料有效。
"conditions": [
{ "category": { "min": 1, "max": 1 }, "measure": { "min": 2, "max": 2 } },
{ "category": { "min": 2, "max": 2 }, "measure": { "min": 1, "max": 1 } }
]
在上述範例中,需要下列兩個條件之一:
- 剛好一個類別欄位,且剛好兩個量值欄位
- 剛好兩個類別欄位,且剛好一個量值欄位
單一資料對應
單一資料對應是資料對應的最簡單形式。 它會接受單一量值欄位,並傳回總計。 如果欄位是數值,則會傳回總和。 否則,會傳回唯一值的計數。
若要使用單一資料對應,請定義要對應的資料角色名稱。 這個對應只使用單一量值欄位。 如果指派了第二個欄位,就不會產生任何資料檢視,因此,建議您納入將資料限制為單一欄位的條件。
注意
此資料對應不能與任何其他資料對應一起使用。 其目的是要將資料縮減為單一數值。
例如:
{
"dataRoles": [
{
"displayName": "Y",
"name": "Y",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"conditions": [
{
"Y": {
"max": 1
}
}
],
"single": {
"role": "Y"
}
}
]
}
產生的資料檢視仍可包含其他類型的對應 (例如資料表或類別),但每個對應只包含單一值。 最佳做法是只在單一對應中存取該值。
{
"dataView": [
{
"metadata": null,
"categorical": null,
"matrix": null,
"table": null,
"tree": null,
"single": {
"value": 94163140.3560001
}
}
]
}
下列程式碼範例處理簡單的資料檢視對應:
"use strict";
import powerbi from "powerbi-visuals-api";
import DataView = powerbi.DataView;
import DataViewSingle = powerbi.DataViewSingle;
// standard imports
// ...
export class Visual implements IVisual {
private target: HTMLElement;
private host: IVisualHost;
private valueText: HTMLParagraphElement;
constructor(options: VisualConstructorOptions) {
// constructor body
this.target = options.element;
this.host = options.host;
this.valueText = document.createElement("p");
this.target.appendChild(this.valueText);
// ...
}
public update(options: VisualUpdateOptions) {
const dataView: DataView = options.dataViews[0];
const singleDataView: DataViewSingle = dataView.single;
if (!singleDataView ||
!singleDataView.value ) {
return
}
this.valueText.innerText = singleDataView.value.toString();
}
}
先前的程式碼範例會顯示來自 Power BI 的單一值:
類別目錄資料對應
類別資料對應是用來取得獨立的資料群組或類別。 您也可以在資料對應中使用「分組依據」,將這些類別分組。
基本類別資料對應
請考慮下列資料角色和對應:
"dataRoles":[
{
"displayName": "Category",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Y Axis",
"name": "measure",
"kind": "Measure"
}
],
"dataViewMappings": {
"categorical": {
"categories": {
"for": { "in": "category" }
},
"values": {
"select": [
{ "bind": { "to": "measure" } }
]
}
}
}
前一範例的內容是「對應我的 category
資料角色,使我拖曳至 category
的每個欄位,其資料都對應到 categorical.categories
。 也將我的 measure
資料角色對應到 categorical.values
」。
- for...in:在資料查詢中納入此資料角色的所有項目。
- bind...to:產生與 for...in 相同的結果,但預期資料角色會受到條件限制,將它侷限於單一欄位。
類別資料分組
下一個範例使用與上一個範例相同的兩個資料角色,並新增兩個名為 grouping
和 measure2
的資料角色。
"dataRoles":[
{
"displayName": "Category",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Y Axis",
"name": "measure",
"kind": "Measure"
},
{
"displayName": "Grouping with",
"name": "grouping",
"kind": "Grouping"
},
{
"displayName": "X Axis",
"name": "measure2",
"kind": "Grouping"
}
],
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"group": {
"by": "grouping",
"select": [{
"bind": {
"to": "measure"
}
},
{
"bind": {
"to": "measure2"
}
}
]
}
}
}
}
]
此對應與基本對應之間的差別在於如何對應 categorical.values
。 當您將 measure
和 measure2
資料角色對應至資料角色 grouping
時,可以適當地調整 x 軸和 Y 軸。
階層式資料分組
在下一個範例中,使用類別資料來建立階層,以支援向下切入動作。
下列範例顯示資料角色和對應:
"dataRoles": [
{
"displayName": "Categories",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measures",
"name": "measure",
"kind": "Measure"
},
{
"displayName": "Series",
"name": "series",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "category"
}
},
"values": {
"group": {
"by": "series",
"select": [{
"for": {
"in": "measure"
}
}
]
}
}
}
}
]
請考慮下列類別資料:
國家/地區 | 2013 | 2014 | 2015 | 2016 |
---|---|---|---|---|
USA | x | x | 650 | 350 |
Canada | x | 630 | 490 | x |
墨西哥 | 645 | x | x | x |
英國 | x | x | 831 | x |
Power BI 會產生類別資料檢視,以及下列一組類別。
{
"categorical": {
"categories": [
{
"source": {...},
"values": [
"Canada",
"USA",
"UK",
"Mexico"
],
"identity": [...],
"identityFields": [...],
}
]
}
}
每個 category
都會對應至一組 values
。 每個 values
都會依 series
分組,以年份表示。
例如,每個 values
陣列都代表一年。
此外,每個 values
陣列都有四個值:加拿大、美國、英國和墨西哥。
{
"values": [
// Values for year 2013
{
"source": {...},
"values": [
null, // Value for `Canada` category
null, // Value for `USA` category
null, // Value for `UK` category
645 // Value for `Mexico` category
],
"identity": [...],
},
// Values for year 2014
{
"source": {...},
"values": [
630, // Value for `Canada` category
null, // Value for `USA` category
null, // Value for `UK` category
null // Value for `Mexico` category
],
"identity": [...],
},
// Values for year 2015
{
"source": {...},
"values": [
490, // Value for `Canada` category
650, // Value for `USA` category
831, // Value for `UK` category
null // Value for `Mexico` category
],
"identity": [...],
},
// Values for year 2016
{
"source": {...},
"values": [
null, // Value for `Canada` category
350, // Value for `USA` category
null, // Value for `UK` category
null // Value for `Mexico` category
],
"identity": [...],
}
]
}
下列程式碼範例示範如何處理類別資料檢視對應。 此範例會建立階層式結構國家/地區 > 年份 > 值。
"use strict";
import powerbi from "powerbi-visuals-api";
import DataView = powerbi.DataView;
import DataViewCategorical = powerbi.DataViewCategorical;
import DataViewValueColumnGroup = powerbi.DataViewValueColumnGroup;
import PrimitiveValue = powerbi.PrimitiveValue;
// standard imports
// ...
export class Visual implements IVisual {
private target: HTMLElement;
private host: IVisualHost;
private categories: HTMLElement;
constructor(options: VisualConstructorOptions) {
// constructor body
this.target = options.element;
this.host = options.host;
this.categories = document.createElement("pre");
this.target.appendChild(this.categories);
// ...
}
public update(options: VisualUpdateOptions) {
const dataView: DataView = options.dataViews[0];
const categoricalDataView: DataViewCategorical = dataView.categorical;
if (!categoricalDataView ||
!categoricalDataView.categories ||
!categoricalDataView.categories[0] ||
!categoricalDataView.values) {
return;
}
// Categories have only one column in data buckets
// To support several columns of categories data bucket, iterate categoricalDataView.categories array.
const categoryFieldIndex = 0;
// Measure has only one column in data buckets.
// To support several columns on data bucket, iterate years.values array in map function
const measureFieldIndex = 0;
let categories: PrimitiveValue[] = categoricalDataView.categories[categoryFieldIndex].values;
let values: DataViewValueColumnGroup[] = categoricalDataView.values.grouped();
let data = {};
// iterate categories/countries-regions
categories.map((category: PrimitiveValue, categoryIndex: number) => {
data[category.toString()] = {};
// iterate series/years
values.map((years: DataViewValueColumnGroup) => {
if (!data[category.toString()][years.name] && years.values[measureFieldIndex].values[categoryIndex]) {
data[category.toString()][years.name] = []
}
if (years.values[0].values[categoryIndex]) {
data[category.toString()][years.name].push(years.values[measureFieldIndex].values[categoryIndex]);
}
});
});
this.categories.innerText = JSON.stringify(data, null, 6);
console.log(data);
}
}
以下是產生的視覺效果:
對應資料表
基本上,資料表資料檢視是可彙總數值資料點的資料點清單。
例如,使用上一節的相同資料,但使用下列功能:
"dataRoles": [
{
"displayName": "Column",
"name": "column",
"kind": "Grouping"
},
{
"displayName": "Value",
"name": "value",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"table": {
"rows": {
"select": [
{
"for": {
"in": "column"
}
},
{
"for": {
"in": "value"
}
}
]
}
}
}
]
將資料表資料檢視視覺化,如下例所示:
國家/地區 | Year | Sales |
---|---|---|
USA | 2016 | 100 |
USA | 2015 | 50 |
Canada | 2015 | 200 |
Canada | 2015 | 50 |
墨西哥 | 2013 | 300 |
英國 | 2014 | 150 |
USA | 2015 | 75 |
資料繫結:
Power BI 會將您的資料顯示為資料表資料檢視。 請勿假設資料已排序。
{
"table" : {
"columns": [...],
"rows": [
[
"Canada",
2014,
630
],
[
"Canada",
2015,
490
],
[
"Mexico",
2013,
645
],
[
"UK",
2014,
831
],
[
"USA",
2015,
650
],
[
"USA",
2016,
350
]
]
}
}
若要彙總資料,請選取所需的欄位,然後選擇 [加總]。
處理資料表資料檢視對應的程式碼範例。
"use strict";
import "./../style/visual.less";
import powerbi from "powerbi-visuals-api";
// ...
import DataViewMetadataColumn = powerbi.DataViewMetadataColumn;
import DataViewTable = powerbi.DataViewTable;
import DataViewTableRow = powerbi.DataViewTableRow;
import PrimitiveValue = powerbi.PrimitiveValue;
// standard imports
// ...
export class Visual implements IVisual {
private target: HTMLElement;
private host: IVisualHost;
private table: HTMLParagraphElement;
constructor(options: VisualConstructorOptions) {
// constructor body
this.target = options.element;
this.host = options.host;
this.table = document.createElement("table");
this.target.appendChild(this.table);
// ...
}
public update(options: VisualUpdateOptions) {
const dataView: DataView = options.dataViews[0];
const tableDataView: DataViewTable = dataView.table;
if (!tableDataView) {
return
}
while(this.table.firstChild) {
this.table.removeChild(this.table.firstChild);
}
//draw header
const tableHeader = document.createElement("th");
tableDataView.columns.forEach((column: DataViewMetadataColumn) => {
const tableHeaderColumn = document.createElement("td");
tableHeaderColumn.innerText = column.displayName
tableHeader.appendChild(tableHeaderColumn);
});
this.table.appendChild(tableHeader);
//draw rows
tableDataView.rows.forEach((row: DataViewTableRow) => {
const tableRow = document.createElement("tr");
row.forEach((columnValue: PrimitiveValue) => {
const cell = document.createElement("td");
cell.innerText = columnValue.toString();
tableRow.appendChild(cell);
})
this.table.appendChild(tableRow);
});
}
}
視覺效果樣式檔案 style/visual.less
包含資料表的配置:
table {
display: flex;
flex-direction: column;
}
tr, th {
display: flex;
flex: 1;
}
td {
flex: 1;
border: 1px solid black;
}
產生的視覺效果看起來像這樣:
矩陣資料對應
矩陣資料對應類似於資料表資料對應,但資料列會以階層方式呈現。 任一個資料角色值都可以用來作為資料行標題值。
{
"dataRoles": [
{
"name": "Category",
"displayName": "Category",
"displayNameKey": "Visual_Category",
"kind": "Grouping"
},
{
"name": "Column",
"displayName": "Column",
"displayNameKey": "Visual_Column",
"kind": "Grouping"
},
{
"name": "Measure",
"displayName": "Measure",
"displayNameKey": "Visual_Values",
"kind": "Measure"
}
],
"dataViewMappings": [
{
"matrix": {
"rows": {
"for": {
"in": "Category"
}
},
"columns": {
"for": {
"in": "Column"
}
},
"values": {
"select": [
{
"for": {
"in": "Measure"
}
}
]
}
}
}
]
}
矩陣資料的階層式結構
Power BI 會建立階層式資料結構。 樹狀結構階層的根包含 Category
資料角色 Parents 資料行中的資料,其中包含來自該資料角色資料表 Children 資料行的下層。
語意模型:
上層 | Children | 下下層 | 資料行 | 值 |
---|---|---|---|---|
Parent1 | Child1 | Grand child1 | col1 | 5 |
Parent1 | Child1 | Grand child1 | Col2 | 6 |
Parent1 | Child1 | Grand child2 | col1 | 7 |
Parent1 | Child1 | Grand child2 | Col2 | 8 |
Parent1 | Child2 | Grand child3 | col1 | 5 |
Parent1 | Child2 | Grand child3 | Col2 | 3 |
Parent1 | Child2 | Grand child4 | col1 | 4 |
Parent1 | Child2 | Grand child4 | Col2 | 9 |
Parent1 | Child2 | Grand child5 | col1 | 3 |
Parent1 | Child2 | Grand child5 | Col2 | 5 |
Parent2 | Child3 | Grand child6 | col1 | 1 |
Parent2 | Child3 | Grand child6 | Col2 | 2 |
Parent2 | Child3 | Grand child7 | col1 | 7 |
Parent2 | Child3 | Grand child7 | Col2 | 1 |
Parent2 | Child3 | Grand child8 | col1 | 10 |
Parent2 | Child3 | Grand child8 | Col2 | 13 |
Power BI 的核心矩陣視覺效果會將資料以表格呈現。
下列程式碼描述視覺效果的資料結構 (這裡只顯示前兩個表格列):
{
"metadata": {...},
"matrix": {
"rows": {
"levels": [...],
"root": {
"childIdentityFields": [...],
"children": [
{
"level": 0,
"levelValues": [...],
"value": "Parent1",
"identity": {...},
"childIdentityFields": [...],
"children": [
{
"level": 1,
"levelValues": [...],
"value": "Child1",
"identity": {...},
"childIdentityFields": [...],
"children": [
{
"level": 2,
"levelValues": [...],
"value": "Grand child1",
"identity": {...},
"values": {
"0": {
"value": 5 // value for Col1
},
"1": {
"value": 6 // value for Col2
}
}
},
...
]
},
...
]
},
...
]
}
},
"columns": {
"levels": [...],
"root": {
"childIdentityFields": [...],
"children": [
{
"level": 0,
"levelValues": [...],
"value": "Col1",
"identity": {...}
},
{
"level": 0,
"levelValues": [...],
"value": "Col2",
"identity": {...}
},
...
]
}
},
"valueSources": [...]
}
}
展開和折疊資料列標頭
若是 API 4.1.0 或更新版本,矩陣資料支援展開和折疊資料列標頭。 從 API 4.2 開始,您可以透過程式設計方式展開/折疊整個層級。 展開和折疊功能可讓使用者展開或折疊資料列,而不擷取下一層級的所有資料,藉此最佳化擷取資料到 dataView。 它只會擷取所選資料列的資料。 資料列標頭的展開狀態會在所有書籤,甚至所有已儲存的報表上保持一致。 而不是每個視覺效果的特定狀態。
藉由將 dataRoles
參數提供給 showContextMenu
方法,將展開和折疊命令新增至操作功能表。
若要展開大量資料點,請使用擷取更多資料 API 搭配展開/折疊 API。
API 功能
下列元素已新增至 API 4.1.0 版,以啟用展開和折疊資料列標頭:
DataViewTreeNode
中的isCollapsed
旗標:interface DataViewTreeNode { //... /** * TRUE if the node is Collapsed * FALSE if it is Expanded * Undefined if it cannot be Expanded (e.g. subtotal) */ isCollapsed?: boolean; }
ISelectionManger
介面中的toggleExpandCollapse
方法:interface ISelectionManager { //... showContextMenu(selectionId: ISelectionId, position: IPoint, dataRoles?: string): IPromise<{}>; // dataRoles is the name of the role of the selected data point toggleExpandCollapse(selectionId: ISelectionId, entireLevel?: boolean): IPromise<{}>; // Expand/Collapse an entire level will be available from API 4.2.0 //... }
DataViewHierarchyLevel 中的
canBeExpanded
旗標:interface DataViewHierarchyLevel { //... /** If TRUE, this level can be expanded/collapsed */ canBeExpanded?: boolean; }
視覺效果需求
若要使用矩陣資料檢視,在視覺效果上啟用展開折疊功能:
在 capabilities.json 檔案中新增下列程式碼:
"expandCollapse": { "roles": ["Rows"], //”Rows” is the name of rows data role "addDataViewFlags": { "defaultValue": true //indicates if the DataViewTreeNode will get the isCollapsed flag by default } },
確認角色是可切入的:
"drilldown": { "roles": ["Rows"] },
針對每個節點,在選取的節點階層層級中呼叫
withMatrixNode
方法並建立selectionId
,以建立選取項目建置者的執行個體。 例如:let nodeSelectionBuilder: ISelectionIdBuilder = visualHost.createSelectionIdBuilder(); // parantNodes is a list of the parents of the selected node. // node is the current node which the selectionId is created for. parentNodes.push(node); for (let i = 0; i < parentNodes.length; i++) { nodeSelectionBuilder = nodeSelectionBuilder.withMatrixNode(parentNodes[i], levels); } const nodeSelectionId: ISelectionId = nodeSelectionBuilder.createSelectionId();
建立選取項目管理員的執行個體,並使用
selectionManager.toggleExpandCollapse()
方法,搭配您為所選節點建立的selectionId
參數。 例如:// handle click events to apply expand\collapse action for the selected node button.addEventListener("click", () => { this.selectionManager.toggleExpandCollapse(nodeSelectionId); });
注意
- 如果選取的節點不是資料列節點,PowerBI 將會忽略展開和折疊呼叫,且會從操作功能表中移除展開和折疊命令。
- 只有在視覺效果支援
drilldown
或expandCollapse
功能時,showContextMenu
方法才需要dataRoles
參數。 如果視覺效果支援這些功能,但未提供 dataRoles,則在使用開發人員視覺效果或啟用偵錯模式來對公用視覺效果進行偵錯時,錯誤將會輸出至主控台。
考量與限制
- 展開節點之後,新的資料限制將會套用至 DataView。 新的 DataView 可能不會包含先前 DataView 中顯示的部分節點。
- 使用展開或折疊時,即使視覺效果未要求,也會新增總計。
- 不支援展開和折疊資料行。
保留所有中繼資料資料行
若是 API 5.1.0 或更新版本,則支援保留所有中繼資料資料行。 此功能可讓視覺效果接收所有資料行的中繼資料,無論其作用中預測資料為何。
將下列幾行新增至 capabilities.json 檔案:
"keepAllMetadataColumns": {
"type": "boolean",
"description": "Indicates that visual is going to receive all metadata columns, no matter what the active projections are"
}
將此屬性設定為 true
,會導致接收所有中繼資料,包括來自折疊的資料行的中繼資料。 將它設定為 false
或保留為未定義,會導致只接收含有作用中預測資料 (例如,展開) 的資料行中繼資料。
資料縮減演算法
資料縮減演算法會控制在資料檢視中接收哪些資料和接收的資料量。
count 會設定為資料檢視可接受的值數目上限。 如果數量超過 count 值,則資料縮減演算法會決定應接收哪些值。
資料縮減演算法類型
資料縮減演算法有四個類型:
top
:第一個 count 值取自語意模型。bottom
:最後一個 count 值取自語意模型。sample
:包含第一個和最後一個項目,以及在它們之間間隔相等的項目數 (count)。 例如,如果您有語意模型 [0, 1, 2, ...100] 且 count 為 9,則您接收到的值為 [0, 10, 20 ...100]。window
:一次載入一個 window 的資料點,其中包含 count 個元素。 目前,top
和window
是相等的。 未來將完全支援 window 設定。
根據預設,所有 Power BI 視覺效果都會套用常見資料縮減演算法,並將 count 設定為 1000 個資料點。 此預設值相當於在 capabilities.json 檔案中設定下列屬性:
"dataReductionAlgorithm": {
"top": {
"count": 1000
}
}
您可以將 count 值修改為最多到 30000 的任何整數值。 以 R 為基礎的 Power BI 視覺效果最多可支援 150000 個資料列。
資料縮減演算法使用方式
資料縮減演算法可以用於類別目錄、資料表或矩陣矩陣資料檢視對應。
在類別資料對應中,您可以將演算法新增至 "categories" 和/或 values
的 "group" 區段中,以進行類別資料對應。
"dataViewMappings": {
"categorical": {
"categories": {
"for": { "in": "category" },
"dataReductionAlgorithm": {
"window": {
"count": 300
}
}
},
"values": {
"group": {
"by": "series",
"select": [{
"for": {
"in": "measure"
}
}
],
"dataReductionAlgorithm": {
"top": {
"count": 100
}
}
}
}
}
}
在資料表資料檢視對應中,將資料縮減演算法套用至資料檢視對應資料表的 rows
區段。
"dataViewMappings": [
{
"table": {
"rows": {
"for": {
"in": "values"
},
"dataReductionAlgorithm": {
"top": {
"count": 2000
}
}
}
}
}
]
您可以將資料縮減演算法套用至資料檢視對應矩陣的 rows
和 columns
區段。