在Microsoft Excel 2013中使用Power Query,我创建了一个如下所示的表:
// To insert this in Power Query, append a '=' before the 'Table.FromRows'
Table.FromRows(
{
{"0", "Tom", "null", "null"},
{"1", "Bob", [ name="Berlin" , street="BarStreet" ], [ name="Mary", age=25 ]},
{"2", "Jim", [ name="Hamburg", street="FooStreet" ], [ name="Marta", age=30 ]}
},
{"ID", "Name", "Address", "Wife"}
)
现在,我想使用Address
属性展开列Wife
和name
在两个记录上。手动,我会这样做:
// To insert this in Power Query, append a '=' before the 'Table.FromRows'
let
t = Table.FromRows(
{
{"0", "Tom", "null", "null"},
{"1", "Bob", [ name="Berlin" , street="BarStreet" ], [ name="Mary", age=25 ]},
{"2", "Jim", [ name="Hamburg", street="FooStreet" ], [ name="Marta", age=30 ]}
},
{"ID", "Name", "Address", "Wife"}
),
expAddress = Table.ExpandRecordColumn(t, "Address", {"name"}, {"Address → name"}),
expWife = Table.ExpandRecordColumn(expAddress, "Wife", {"name"}, {"Wife → name"})
in
expWife
每当我有不同布局的数据表时,我需要重写 查询。在幻想世界中,您可以扩展所有包含记录的列 他们使用特定的密钥。 理想情况下,您将拥有以下库 功能:
// Returns a list with the names of the columns that match the secified type.
// Will also try to infer the type of a column if the table is untyped.
Table.ColumnsOfTypeInfer(
table as table,
listOfTypes as list
) as list
// Expands a column of records into columns with each of the values.
Table.ExpandRecordColumnByKey(
table as table,
columns as list,
key as text,
) as table
然后,我可以打电话
// To insert this in Power Query, append a '=' before the 'Table.FromRows'
let
t = Table.FromRows(
{
{"0", "Tom", "null", "null"},
{"1", "Bob", [ name="Berlin" , street="BarStreet" ], [ name="Mary", age=25 ]},
{"2", "Jim", [ name="Hamburg", street="FooStreet" ], [ name="Marta", age=30 ]}
},
{"ID", "Name", "Address", "Wife"}
),
recordColumns = Table.ColumnsOfTypeInfer(t, {type record}),
expAll = Table.ExpandRecordColumnByKey(t, recordColumns, "name")
in
expAll
答案 0 :(得分:2)
(首先,感谢明确的解释以及样本数据和建议!)
1)M代码无法进行类型推断。这个限制几乎可以被认为是一个"功能",因为如果源数据以导致推断类型不同的方式发生变化,它几乎肯定会破坏您的查询。
加载无类型数据后,应该快速使用Detect Data Type按钮为此生成M.或者,如果您正在从JSON读取数据,那么它应该已经足够输入了。
如果您有一个特定的情况,这不起作用想要更新您的问题? :)
2)只要表的单元格值是记录,它就非常可能并且只有一点点令人费解以使记录扩展成为通用的。这会找到所有行都为null
或记录的列,并展开name
列。
以下是您可以添加到库中的一些简单实现:
let
t = Table.FromRows(
{
{"0", "Tom", null, null},
{"1", "Bob", [ name="Berlin" , street="BarStreet" ], [ name="Mary", age=25 ]},
{"2", "Jim", [ name="Hamburg", street="FooStreet" ], [ name="Marta", age=30 ]}
},
{"ID", "Name", "Address", "Wife"}
),
Table.ColumnsOfAllRowType = (table as table, typ as type) as list => let
ColumnNames = Table.ColumnNames(table),
ColumnsOfType = List.Select(ColumnNames, (name) =>
List.AllTrue(List.Transform(Table.Column(table, name), (cell) => Type.Is(Value.Type(cell), typ))))
in
ColumnsOfType,
Table.ExpandRecordColumnByKey = (table as table, columns as list, key as text) as table =>
List.Accumulate(columns, table, (state, columnToExpand) =>
Table.ExpandRecordColumn(state, columnToExpand, {key}, { columnToExpand & " → " & key })),
recordColumns = Table.ColumnsOfAllRowType(t, type nullable record),
expAll = Table.ExpandRecordColumnByKey(t, recordColumns, "name")
in
expAll
如果只能在M中实现新的库函数,我们就不太可能将它添加到我们的标准库中,但是如果您觉得它丢失了,请随时在https://ideas.powerbi.com/forums/265200-power-bi/ }
你可能有一个很好的论据来添加Table.ReplaceTypeFromFirstRow(table as table) as table
这样的东西,因为用M构造类型非常混乱。
答案 1 :(得分:0)
很抱歉有点迟到,但我遇到了类似的挑战。我尝试使用Chris Webb的ExpandAll函数:
http://blog.crossjoin.co.uk/2014/05/21/expanding-all-columns-in-a-table-in-power-query/
...但是这只适用于Table类型的列,而不是Record-type列,但我已经设法将其破解为此目的。我将Chris的功能复制为“ExpandAllRecords”并进行了3次编辑:
each if _ is table then Table.ColumnNames(_)
替换为each if _ is record then Record.FieldNames(_)
Table.ExpandTableColumn
替换为Table.ExpandRecordColumn
ExpandAll
替换为ExpandAllRecords
我尝试在一个函数中扩展表和记录,但我一直遇到类型错误。
无论如何,有了这个,最后的查询就是:
let
t = Table.FromRows(
{
{"1", "Tom", null, [ name="Jane", age=35 ]},
{"2", "Bob", [ name="Berlin" , street="BarStreet" ], [ name="Mary", age=25 ]},
{"3", "Jim", [ name="Hamburg", street="FooStreet" ], [ name="Marta", age=30 ]}
},
{"ID", "Name", "Address", "Wife"}
),
Output = ExpandAllRecords(t)
in
Output
出于担心,有一天这个伟大的片段(由ChrisMob,由@MikeHoney提到)有一天会消失),我将在这里反映整个代码:
let //Define function taking two parameters - a table and an optional column number Source = (TableToExpand as table, optional ColumnNumber as number) => let //If the column number is missing, make it 0 ActualColumnNumber = if (ColumnNumber=null) then 0 else ColumnNumber, //Find the column name relating to the column number ColumnName = Table.ColumnNames(TableToExpand){ActualColumnNumber}, //Get a list containing all of the values in the column ColumnContents = Table.Column(TableToExpand, ColumnName), //Iterate over each value in the column and then //If the value is of type table get a list of all of the columns in the table //Then get a distinct list of all of these column names ColumnsToExpand = List.Distinct(List.Combine(List.Transform(ColumnContents, each if _ is table then Table.ColumnNames(_) else {}))), //Append the original column name to the front of each of these column names NewColumnNames = List.Transform(ColumnsToExpand, each ColumnName & "." & _), //Is there anything to expand in this column? CanExpandCurrentColumn = List.Count(ColumnsToExpand)>0, //If this column can be expanded, then expand it ExpandedTable = if CanExpandCurrentColumn then Table.ExpandTableColumn(TableToExpand, ColumnName, ColumnsToExpand, NewColumnNames) else TableToExpand, //If the column has been expanded then keep the column number the same, otherwise add one to it NextColumnNumber = if CanExpandCurrentColumn then ActualColumnNumber else ActualColumnNumber+1, //If the column number is now greater than the number of columns in the table //Then return the table as it is //Else call the ExpandAll function recursively with the expanded table OutputTable = if NextColumnNumber>(Table.ColumnCount(ExpandedTable)-1) then ExpandedTable else ExpandAll(ExpandedTable, NextColumnNumber) in OutputTable in Source
然后,您可以在XML文件上使用此函数,如下所示:
let //Load XML file Source = Xml.Tables(File.Contents("C:\Users\Chris\Documents\PQ XML Expand All Demo.xml")), ChangedType = Table.TransformColumnTypes(Source,{{"companyname", type text}}), //Call the ExpandAll function to expand all columns Output = ExpandAll(ChangedType) in Output
(来源和可下载示例: Chris Webb's Bi Blog, 2014-05-21 )