图片文件下载
文件下载需求在页面中显示超链接点击超链接后弹出下载提示框。完成图片文件下载。分析步骤:定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename定义Servlet 1. 获取文件名称。 2. 使用字节输入流加载文件进内存。 3. 指定response的响应头: content-disposition:attachment;filen...
Power BI数据清洗避坑指南:从Power Query菜单到M语言代码的完整心法
当你第一次打开Power Query编辑器,面对密密麻麻的菜单按钮和陌生的M语言代码,是否感到无从下手?数据清洗作为数据分析的基石,直接决定了后续建模和可视化的质量。本文将带你避开常见陷阱,建立从界面操作到代码原理的完整知识体系。
1. 脏数据识别与初步处理
拿到一份销售订单与客户信息混合的Excel表格时,首先需要培养"数据侦探"的敏锐度。常见的脏数据特征包括:
- 不一致的格式 :日期列中混用"2023/01/01"和"01-Jan-2023"
- 缺失值陷阱 :空白单元格可能显示为null、NA或直接留空
- 异常值干扰 :销售额列中出现负值或明显超出合理范围的数值
- 重复记录 :同一订单ID出现多次但细节信息不一致
第一步总是先创建备份 :在Power Query编辑器中右键点击查询→选择"复制",保留原始数据副本。我曾见过同事因直接修改原始查询导致整个项目需要重做。
数据类型转换是新手最容易犯错的地方。点击列标题左侧的 ABC 图标时,系统会尝试自动判断类型,但经常出错。更可靠的做法是:
= Table.TransformColumnTypes(源, {{"订单日期", type date}})
注意:转换失败的值会变成红色错误提示,此时应检查原始数据而非强制转换
2. Power Query界面操作的黄金法则
2.1 菜单功能的战略选择
"主页"选项卡中的 删除行 功能有多个子选项,90%的情况只需要使用 删除空行 和 删除重复项 。我曾花费两小时调试一个公式,最后发现只是需要先执行 删除空行 。
"转换"选项卡中的 拆分列 功能看似简单,但选择 按分隔符 还是 按字符数 会导致完全不同的结果。对于地址字段,建议先用:
= Table.SplitColumn(源, "地址", Splitter.SplitTextByDelimiter(" ", QuoteStyle.Csv), {"地址.1", "地址.2"})
关键原则 :每次操作后立即在右侧"查询设置"窗格中为步骤命名(如"删除测试订单"),三个月后你会感谢这个习惯。
2.2 添加列的三种智慧
- 条件列 :处理业务规则最安全的方式
= Table.AddColumn(源, "客户等级", each if [销售额] > 10000 then "VIP" else "普通") - 索引列 :看似简单却是解决合并问题的钥匙
- 自定义列 :灵活但需要M语言基础,新手建议先用界面操作生成代码再修改
3. 高级技巧与M语言原理
3.1 合并查询的隐藏成本
使用 合并查询 功能时,系统默认保留所有行(左外连接),这可能导致数据膨胀。实际业务中更常用的是:
= Table.NestedJoin(订单表, {"客户ID"}, 客户表, {"ID"}, "客户详情", JoinKind.Inner)
连接类型对照表:
| JoinKind参数 | SQL等效 | 适用场景 |
|---|---|---|
| Inner | INNER JOIN | 只保留匹配记录 |
| LeftOuter | LEFT JOIN | 保留左表全部 |
| RightOuter | RIGHT JOIN | 保留右表全部 |
| FullOuter | FULL OUTER JOIN | 保留所有记录 |
3.2 透视与逆透视的艺术
销售数据经常以交叉表形式存在(月份作为列标题),此时 逆透视 是必备技能。但要注意:
- 先选择需要保留的列(如产品ID)
- 然后Ctrl+点击要转换的月份列
- 右键选择
逆透视列
生成的M代码实际上执行了:
= Table.UnpivotOtherColumns(源, {"产品ID"}, "属性", "值")
4. 调试与性能优化
当查询运行缓慢时,检查"查询诊断"工具(视图→查询诊断)。常见性能瓶颈:
- 过早的类型转换 :应在所有清洗完成后最后统一转换
- 不必要的计算列 :能用
Table.AddColumn就不用在DAX中创建计算列 - 低效的合并方式 :小表合并到大表时使用
Table.Join而非界面操作
高级编辑器中的每个步骤都对应一个变量,可以通过临时注释部分代码来隔离问题。例如:
let
源 = Excel.CurrentWorkbook(){[Name="订单"]}[Content],
// 删除测试 = Table.SelectRows(源, each [订单类型] <> "测试"),
类型转换 = Table.TransformColumnTypes(删除测试, {...})
in
类型转换
数据清洗从来不是一次性工作。建立可复用的函数库(如统一地址清洗函数)才是专业做法。在空白查询中输入:
= (inputText as text) => Text.Proper(Text.Trim(inputText))
将其保存为"格式化文本"函数,以后任何查询都可以调用这个标准化流程。
更多推荐



所有评论(0)