题目:
如图,从左表到右表,提取各指标中TOP5所对应的姓名。
解法1:
常规思路,逆透视后分组,排序并添加索引,筛选出TOP5然后展开。
let 源 = Excel.CurrentWorkbook(){[Name="表1"]}[Content], 逆透视 = Table.UnpivotOtherColumns(源, {"姓名"}, "属性", "值"), 分组 = Table.Group(逆透视, {"属性"}, {"a", each Table.TransformColumns(Table.FirstN(Table.AddIndexColumn(Table.Sort(_,{"值",1}),"排名",1,1),5),{"排名",each "TOP"&Text.From(_)})}), 展开 = Table.ExpandTableColumn(分组, "a", {"姓名", "排名"}), 合并 = Table.AddColumn(展开, "类别", each [属性]&[排名]), 删除 = Table.RemoveColumns(合并,{"属性", "排名"}) in 删除
解法2:
直接使用#table
构建表格,配合List.Transform
得到每个指标的子表然后合并,一步出结果但是会比较难理解。
let 源 = Excel.CurrentWorkbook(){[Name="表1"]}[Content], 结果 = Table.Combine(List.Transform(List.Skip(Table.ColumnNames(源)),each #table({"指标编号","姓名"},List.Zip({List.Transform({"1".."5"},(x)=>_&"TOP"&x),Table.FirstN(Table.Sort(源,{_,1}),5)[姓名]})))) in 结果
用replacevalue的思路
厉害
咨询一下,上面n里面的v是代表分组后表吗?最里层替换和外面排序是谁先谁后?感觉是不是先对v进行排序在进行替换比较合理?
怎样才能发你这种带编程框的评论
试了一下这个答案是错误的。
老师好:我的做法:在Power Query逆透视列后加载到PowerPivo,运用RANKX结合EARLIER对值进行排名(=RANKX(FILTER('表1[属性]=EARLIER('表1[属性])),[值])),透视后也基本达到要求。但是若要达到您所示效果,还要增加几列。
let
源 = Excel.CurrentWorkbook(){[Name="表1"]}[Content],
逆透视的其他列 = Table.UnpivotOtherColumns(更改的类型, {"姓名"}, "属性", "值"),
分组的行 = Table.ExpandTableColumn(Table.Group(
逆透视的其他列, {"属性"}, {{"计数", each
[ t1 = Table.Sort(_,{{"值", Order.Descending}}),
t2 = Table.AddIndexColumn(t1, "top名次", 1 , 1),
t3 = Table.SelectRows(t2, each [top名次] <= 5),
t4 = Table.AddColumn(t3,"top",each Text.From([属性])&"top"&Text.From([top名次]))
][t4]
}} )
, "计数", {"姓名", "top"}, {"姓名", "top"}),
删除的列 = Table.RemoveColumns(分组的行,{"属性"})
in
删除的列
施神:
解法2:中的--------Table.Sort(源,{_,1}
我单独拿出来用会出现“Expression.Error: 指定的排序条件无效。”的提示。
请问这里的下划线“_”应该怎么去理解,上下文环境是什么。能不能帮忙解答下。
逐个提取除姓名外的列名,先构建类别列,后面构建姓名列,用list.zip压缩成对,再用#table构建成表,最后合并
简直是神思路,佩服阳神
还是施老师方法二简单,接近普通思维模式。代码也简单。
敢问施神:
方法二如要加上各对应指标的分数,怎么处理最为简单?
谢谢
表[姓名]可以深化列,each 表[_]提示出错,找不到表的 _ 列
同求阳神+1
表[列]的方法只适用于固定的列名,不适用于变量,可以用函数Table.Column(表,_)代替
感谢阳神解答,给您32个赞!!!
let
源 = Excel.CurrentWorkbook(){[Name="表1"]}[Content],
结果 = Table.Combine(List.Transform(List.Skip(Table.ColumnNames(源)),each #table({"指标编号","姓名","成绩"},List.Zip({List.Transform({"1".."5"},(x)=>_&"TOP"&x),Table.MaxN(源, _ ,5)[姓名],Table.Column (Table.MaxN(源, _ ,5),_)}))))
in
结果
let
源 = Excel.CurrentWorkbook(){[Name="表1"]}[Content],
指标 = List.Skip(Table.ColumnNames(源)),
自定义1 = Table.Combine(List.Transform(指标,each Table.SelectColumns(Table.TransformColumns(Table.AddIndexColumn(Table.MaxN(源,_,5),"top",1),{"top",(x)=>_&Number.ToText(x,"top0")}),{"top","姓名"}) ))
in
自定义1
let
源 = Excel.CurrentWorkbook(){[Name="表1"]}[Content],
转换 = Table.ToColumns( 源),
组合 = Table.Combine( List.Transform({1..List.Count(转换)-1},each Table.AddIndexColumn(Table.AddColumn(Table.MaxN(Table.FromColumns({转换{0},转换{_}},
{"姓名","分数"}),
"分数",5),
"指标",(n)=>"指标"&Text.From(_)&"TOP"),
"a",1))),
合并 = Table.CombineColumns(Table.TransformColumnTypes(组合, {"a", type text}),{"指标", "a"},each Text.Combine(_,""),"指标排名")
in
合并
多做点,顺便把分数带出来
楼主的源代码,格式调整一下就容易理解了
let
源 = Excel.CurrentWorkbook(){[Name="表1"]}[Content],
结果 =
Table.Combine //合并构建出来的全部表格
(
List.Transform
(
List.Skip(Table.ColumnNames(源)), //源表表头所构成的List 去除"姓名",后文中的_指代该列表
each #table //构建表
(
{"指标编号","姓名"}, //表头
List.Zip
(
{
List.Transform({"1".."5"},(x)=>_&"TOP"&x), //[指标编号]列为 各指标&TOP1..5
Table.FirstN(Table.Sort(源,{_,1}),5)[姓名] //对源表分别根据各指标排序,取各指标的前5项的姓名
}
)
)
)
)
in
结果