了解 Power BI 视觉对象中的数据视图映射

  • 版本 :2023.1(当前版本)

了解 Power BI 视觉对象中的数据视图映射

本文介绍数据视图映射,并说明如何使用数据角色创建不同类型的视觉对象。 本文说明了如何指定数据角色的条件要求以及不同 dataMappings 类型。

每个有效映射都会生成数据视图。 在某些情况下,可以提供多个数据映射。 支持的映射选项有:

  • 条件

  • categorical

  • single

  • table

  • 矩阵

JSON复制

"dataViewMappings": [
{ "conditions": [ ... ], "categorical": { ... }, "single": { ... }, "table": { ... }, "matrix": { ... }
}
]

当且仅当在 dataViewMappings 中定义了有效映射时,Power BI 才会创建到数据视图的映射。

换句话说,categorical 可在 dataViewMappings 中定义,但其他映射(例如 tablesingle )可能不行。 在这种情况下,Power BI 会生成具有单个 categorical 映射的数据视图,并且 table 和其他映射仍保持未定义状态。 例如:

JSON复制

"dataViewMappings": [
{ "categorical": { "categories": [ ... ], "values": [ ... ]
}, "metadata": { ... }
}
]

条件

conditions 部分建立特定数据映射的规则。 如果数据与所述的一组条件相匹配,则视觉对象会将数据作为有效数据来接受。

目前,对于每个字段,可以指定最小值和最大值。 该值表示可以绑定到该数据角色的字段数。

备注

如果条件中省略了数据角色,那么可以绑定任意数量的字段。

在以下示例中,将 category 限制为一个数据字段,并将 measure 限制为两个数据字段。

JSON复制

"conditions": [
{ "category": { "max": 1 }, "measure": { "max": 2 } },
]

还可以为数据角色设置多个条件。 在这种情况下,如果满足其中任何一个条件,则数据是有效的。

JSON复制

"conditions": [
{ "category": { "min": 1, "max": 1 }, "measure": { "min": 2, "max": 2 } },
{ "category": { "min": 2, "max": 2 }, "measure": { "min": 1, "max": 1 } }
]

在上面的示例中,需要满足以下两个条件之一:

  • 一个类别字段和两个度量值

  • 两个类别和一个度量值。

单个数据映射

单个数据映射是数据映射的最简单形式。 它接受单个度量值字段并返回总计。 如果该字段为数值,则返回总和。 否则,它返回非重复值的计数。

要使用单个数据映射,则定义要映射的数据角色的名称。 此映射仅适用于单个度量值字段。 如果分配了第二个字段,则不会生成任何数据视图,因此,最好包含将数据限制为单个字段的条件。

备注

此数据映射不能与任何其他数据映射结合使用。 它旨在将数据减少到单个数值。

例如:

JSON复制

{    "dataRoles": [
{ "displayName": "Y", "name": "Y", "kind": "Measure"
}
], "dataViewMappings": [
{ "conditions": [
{ "Y": { "max": 1
}
}
], "single": { "role": "Y"
}
}
]
}

生成的数据视图仍可包含其他类型(表、类别等),但每个映射只包含单个值。 最佳做法是只访问单个值。

JSON复制

{    "dataView": [
{ "metadata": null, "categorical": null, "matrix": null, "table": null, "tree": null, "single": { "value": 94163140.3560001
}
}
]
}

处理简单数据视图映射的代码示例

TypeScript复制

"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 中的单个值:

单个数据视图映射视觉对象的示例

类别数据映射

分类数据映射用于获取独立的数据组别或类别。 还可以使用数据映射中的“分组依据”进一步将类别分为一个组。

基本分类数据映射

请考虑以下数据角色和映射:

JSON复制

"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 相同的结果,但预期数据角色具有将其限制为单个字段的条件 。

对分类数据进行分组

下一示例使用与上一示例相同的两个数据角色,并添加名为 groupingmeasure2 的数据角色。

JSON复制

"dataRole":[
{ "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 的方式不同。 通过将 measuremeasure2 数据角色映射到数据角色 grouping,可以适当地缩放 x 轴和 y 轴。

对分层数据进行分组

在下一示例中,我们将使用分类数据创建层次结构,该层次结构可用于支持向下钻取操作。

下面是数据角色和映射:

JSON复制

"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"
}
}
]
}
}
}
}
]

请考虑以下分类数据:

国家/地区2013201420152016
USAxx650350
加拿大x630490x
墨西哥645xxx
英国xx831x

Power BI 会生成具有以下一组类别的分类数据视图。

JSON复制

{    "categorical": {        "categories": [
{ "source": {...}, "values": [ "Canada", "USA", "UK", "Mexico"
], "identity": [...], "identityFields": [...],
}
]
}
}

每个 category 也会映射到一组 values。 其中每个 values 都按 series(以年份形式表示)进行分组。

例如,每个 values 数组表示一年。 此外,每个 values 数组都有四个值:加拿大、美国、英国和墨西哥:

JSON复制

{    "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": [...],
}
]
}

下面是用于处理分类数据视图映射的代码示例。 此示例创建层次结构 Country => Year => Value

TypeScript复制

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

生成的视觉对象如下所示:

具有分类数据视图映射的视觉对象

映射表

实质上,表数据视图是数据点的列表,可在其中聚合数值数据点。

例如,使用上一部分中的相同数据,但具有以下功能:

JSON复制

"dataRoles": [
{ "displayName": "Column", "name": "column", "kind": "Grouping"
},
{ "displayName": "Value", "name": "value", "kind": "Measure"
}
],"dataViewMappings": [
{ "table": { "rows": { "select": [
{ "for": { "in": "column"
}
},
{ "for": { "in": "value"
}
}
]
}
}
}
]

可以按如下方式可视化表数据视图:

数据示例:

国家/地区YearSales
USA2016100
USA201550
加拿大2015200
Canada201550
墨西哥2013300
英国2014150
USA201575

数据绑定:

表数据视图映射数据绑定

Power BI 以表数据视图的形式显示数据。 不假定数据已排序。

JSON复制

{    "table" : {        "columns": [...],        "rows": [
[ "Canada", 2014, 630
],
[ "Canada", 2015, 490
],
[ "Mexico", 2013, 645
],
[ "UK", 2014, 831
],
[ "USA", 2015, 650
],
[ "USA", 2016, 350
]
]
}
}

若要聚合数据,请选择所需的字段,然后选择“求和”。

数据聚合。

处理表数据视图映射的代码示例。

TypeScript复制

"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 包含表的布局:

less复制

table {    display: flex;    flex-direction: column;
}tr, th { display: flex; flex: 1;
}td { flex: 1; border: 1px solid black;
}

生成的视觉对象如下所示:

具有表数据视图映射的视觉对象。

矩阵数据映射

矩阵数据映射与表数据映射类似,但前者按层次结构显示行。 任意一个数据角色值均可用作列标题值。

JSON复制

{    "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 数据角色的“父级”列数据,以及来自数据角色表的“子级”列的子项

数据集:

父项子女孙级
Parent1Child1Grand child1Col15
Parent1Child1Grand child1Col26
Parent1Child1Grand child2Col17
Parent1Child1Grand child2Col28
Parent1Child2Grand child3Col15
Parent1Child2Grand child3Col23
Parent1Child2Grand child4Col14
Parent1Child2Grand child4Col29
Parent1Child2Grand child5Col13
Parent1Child2Grand child5Col25
Parent2Child3Grand child6Col11
Parent2Child3Grand child6Col22
Parent2Child3Grand child7Col17
Parent2Child3Grand child7Col21
Parent2Child3Grand child8Col110
Parent2Child3Grand child8Col213

Power BI 的核心矩阵视觉对象将数据呈现为表。

矩阵视觉对象。

视觉对象按以下代码所述获取其数据结构(此处仅显示前两个表行):

JSON复制

{    "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 开始,矩阵数据将支持展开和折叠行标题。 展开/折叠功能允许用户展开或折叠行,而无需提取下一级别的所有数据,从而优化了将数据提取到 dataView。 它仅提取所选行的数据。 行标题的展开状态将在书签之间甚至在报告保存之间保持一致。 它并不特定于每个视觉对象。

也可以通过将 dataRoles 参数提供给 showContextMenu 方法,将展开和折叠命令添加到上下文菜单中。

屏幕截图显示带有“展开”和“折叠”选项的上下文菜单。

API 功能

为了能够展开和折叠行标题,在 API 版本 4.1.0 中增加了以下内容。

  • isCollapsed 中的 DataViewTreeNode 标志:

    TypeScript复制

    interface DataViewTreeNode {    //...
    /**
    * TRUE if the node is Collapsed
    * FALSE if it is Expanded
    * Undefined if it cannot be Expanded (e.g. subtotal)
    */
    isCollapsed?: boolean;
    }
  • toggleExpandCollapse 接口中的 ISelectionManger 方法:

    TypeScript复制

    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
    //...}
  • DataViewTreeNodeValue 中的 canBeExpanded 标志:

    TypeScript复制

    interface DataViewHierarchyLevel {    //...
    /** If TRUE, this level can be expanded/collapsed */
    canBeExpanded?: boolean;
    }

视觉对象要求

使用矩阵数据视图对视觉对象启用展开/折叠功能:

  1. 将以下内容添加到 capabilities.json 文件中:

    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 
    }
    },
  2. 确保角色是可钻取的:

    JSON复制

        "drilldown": {    "roles": ["Rows"]
    },
  3. 对于每个节点,创建选择生成器的实例,在所选节点层次结构级别调用 withMatrixNode 方法并创建 selectionId。 例如:

    TypeScript复制

        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 const nodeSelectionId: ISelectionId = nodeSelectionBuilder.createSelectionId();

  4. 创建选择管理器的实例,并将 selectionManager.toggleExpandCollapse() 方法与为所选节点创建的 selectionId 的参数一起使用。 例如:

    TypeScript复制

        // handle click events to apply expand\collapse action for the selected node
    button.addEventListener("click", () => { this.selectionManager.toggleExpandCollapse(nodeSelectionId);
    });

备注

  • 如果所选节点不是行节点,则 PowerBI 将忽略展开/折叠调用,并将从上下文菜单中删除展开/折叠命令。

  • 只有在视觉对象支持 drilldownexpandCollapse 功能时,showContextMenu 方法才需要 dataRoles 参数。 如果视觉对象支持这些功能,但未提供 dataRoles,则在使用开发者视觉对象或调试启用了调试模式的公共视觉对象时,将向控制台输出一个错误。

注意事项和限制

  • 展开节点后,新的数据限制将应用到 DataView。 这意味着新的 DataView 可能不包括以前的 DataView 中出现的某些节点。

  • 使用展开/折叠时,即使视觉对象未请求,也会添加合计。

  • 当前,不支持展开和折叠列。

保留所有元数据列

从 API 5.1.0 开始,将支持保留所有元数据列。 此功能允许视觉对象接收所有列的元数据,无论其活动投影是什么。

将以下行添加到 capabilities.json 文件中:

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:一次加载一个“窗口”的数据点,其中包含“count”元素 。 当前 topwindow 等效。 我们正在努力做到完全支持窗口设置。

默认情况下,所有 Power BI 视觉对象都应用了顶级数据缩减算法,并将“count”设置为 1000 个数据点。 这相当于在 capabilities.json 文件中设置了以下属性:

JSON复制

"dataReductionAlgorithm": {    "top": {        "count": 1000
}
}

可以将“count”值修改为不超过 30000 的任何整数值。 基于 R 的 Power BI 视觉对象最多可支持 150000 行。

数据缩减算法使用情况

数据缩减算法可用于分类、表或矩阵数据视图映射。

在分类数据映射中,可以将此算法添加到分类数据映射的 values 的“类别”和/或“组”部分。

JSON复制

"dataViewMappings": {    "categorical": {        "categories": {            "for": { "in": "category" },            "dataReductionAlgorithm": {                "window": {                    "count": 300
}
}
}, "values": { "group": { "by": "series", "select": [{ "for": { "in": "measure"
}
}
], "dataReductionAlgorithm": { "top": { "count": 100
}
}
}
}
}
}

在表数据视图映射中,可以将数据缩减算法应用于数据视图映射表的 rows 部分。

JSON复制

"dataViewMappings": [
{ "table": { "rows": { "for": { "in": "values"
}, "dataReductionAlgorithm": { "top": { "count": 2000
}
}
}
}
}
]

可以将数据缩减算法应用于数据视图映射矩阵的 rowscolumns 部分。