Python连接SQL Server并存储数据之前的数据库都是使用的mysql。由于powerbi 使用sql server更方便，将后续的资料开始使用python转存到SQL server里面。连接方法python的好处就在于对于不同的DB，只要调整前端的接口，后面的写入方法都不用调整。所以我们找到合适的连接sql server的connection即可。之前使用的是pymysql,现在将包换成pymssql即可。import pandas as pd from sqlalchemy import create_engine import pymssql # 替换以下连接信息 server = '192.1.1.1' database = 'xxxx' username = 'user' password = 'abc' # 创建数据库引擎 connection_string = f'mssql+pymssql://{username}:{password}@{server}:1433/{database}' engine = create_engine(connection_string) try: # 尝试连接并执行简单查询 with engine.connect() as conn: result = pd.read_sql("SELECT 1", conn) print("数据库连接成功！") except Exception as e: print(f"连接失败：{str(e)}") df2 = pd.read_csv("test.csv") print(df2.head(5)) df2.to_sql("table name", engine, if_exists="append", index=False) # print(df) 问题整理使用odbc驱动时，会报如下异常错误。有人说使用高版本的drive可以解决。测试仍然不行，更换pymssql后没有问题。sqlalchemy.exc.DBAPIError: (pyodbc.Error) ('HY104', '[HY104] [Microsoft][ODBC SQL Server Driver]無效的有效位數值 (0) (SQLBindParameter)')sql server的默认表都有dbo 实际调用的过程中，不用特别输入。目前在数据处理和清洗过程中使用Pandas的频率最高，后期待整理常用的方法。
PowerBI 建模反思十一之后，新学了几个DAX函数，但还都是刚熟悉，没有具体的使用场景。所以暂时不做分享。这一期分享一个关于在使用powerbi容易遇到的坑（建模）。为什么这么说呢？因为我们最初接触别人分享这个软件时，他们都会提供给我们一个样本文件或者excel数据。接下来，我们只要导入这个数据，然后系统会自动帮我们建模。我们就可以直接拖拽一些值进行制作图表了。然而，当我们自己导入实际生产的数据时，立即发现问题了。拖出来的数据用不了或者不准确。真是一看就会，一用就废。我们在回头看案例的数据时，发现他们的模型都是设计过的。而我们的数据由于各种原因，比如列名不同，对应关系不合理等，系统不会帮我们匹配。所以我们需要一点点数据库的基础知识，然后要自己设计这个匹配模型。只有这样，才能方便后续的使用。当有一个合理的模型时，我们可以减少一些复杂的逻辑去实现。不然，DAX就变的很复杂。而常规的建模官方给的建议是STAR模型。STAR模型官方给出的模型示例是一个五角星形状。各个角对应的是维度表，而中间是具体事实表。当我们使用这种方式建模，其实就是使用的一对多关系来匹配。同时尽量避免了多对多导致的一些偏差。在具体使用过程中，我们有时可能只会拿到一个事实表。就是所有的资料都在一个excel表格里面。我们要做的就是先去提取这些维度表，然后进行设计。日期表正常的日期表一般是直接用calendar()生成，其中可以用max,min去获取事实表的最大最小日期。其他维度使用新建表然后用values()获取某一列的唯一值，然后将新表建立与事实表的关系。如果是两个表某一列的合并，可以使用union连接两个表的值后进行获取维度表。
PowerBI使用SVG绘制图表八月底更新的一篇关于PowerBI函数的用法还上了推荐。所以看起来，现在这个使用人群还不少。所以今天更新一个帮别人绘制图形的思路和制作方法。Powerbi制作要求在powerBI 里面绘制一个图形，用统计值和标准值去做对比。针对比对的大小，分别用红绿灯填充。我们来分析一下这个图:X轴使用的是时间维度Y轴这里比较奇怪，使用的是产品名称维度在图表中的值，没有大小区分，只是有颜色的差异。在图一中，我们可以切换统计的维度，就是统计值可以是最大值，最小值，平均值等。PowerBi制作思路大部分人看到这个图的第一想法就是，这不就是散布图么？ 看起来难度不大。但是当我们实操的时候会发现，X轴可以放上去，Y轴是放不上去产品名称的。为何呢？问了下GPT回答如下：如果你尝试在Y轴上放置非数值型数据（如产品类型），可能会遇到数据类型限制：散点图要求X轴和Y轴的数据是数值型，以便能够在二维平面上精确定位每个数据点的位置。非数值数据（如文本或类别）无法直接用于散点图的数值轴。原来散点图会要求Y轴必须是数据类型来做匹配。使用charticulator插件绘制遇到上面的问题之后，我想到的第一个思路就是用这个制图神器去实现这个效果。先放上制作成品。在这个插件里面，取消了对Y轴的限制，所以我们可以直接把产品类型放进去。自动会生成原点图。我们需要配置的是将比较的结果返回的字符串匹配到颜色上面去。如下图所示。这样我们基本上就可以制作完成。有一个缺陷是，当我们使用字段参数时，图形会要求我们重新匹配传入的值，所以在使用过程中有些不方便。当然我们也可以做成多个图来展示。填SVG到矩阵里面实现使用另外一个思路也可以实现，因为红绿灯显示，我们可以制作两个SVG，放入返回的结果里面去。这样在矩阵里面就可以展示红绿灯了，而且这样做的好处是可以支持字段参数。制作的成品效果如下：这个步骤要比上面的复杂一些。写两个DAX函数用于对应红色和蓝色的SVG.BlueCircleSVG = "data:image/svg+xml;utf8, <circle cx='10' cy='10' r='10' fill='blue' /> " RedCircleSVG = "data:image/svg+xml;utf8, <circle cx='10' cy='10' r='10' fill='red' /> " 替换原DAX中返回的"Red" 和"Blue"为对应的SVG度量值修改数据格式，这一步最重要，不然你会在矩阵里面看到的一大串文字。选中相应的度量值，然后修改为如下样式：将对应的度量值拖入矩阵即可展示出成果。总结在展示数据时，我们可能会遇到各种局限，而使用charticulator可以帮助我们破除这些限制。当然它本身也有限制，传入的一些值动态变换能力不够。所以我们可以考虑用变通的方法来实现最终的目的。这次制作我也是第一次正式使用SVG去填充一些信息。在上面的第三步由于只修改了SVG默认的格式，返回值DAX忘记修改了，所以在显示的时候一直是文字而不是图形。
RankX的用法- 定义 - 当使用RANKX函数时，它将返回基于给定表达式的排序顺序的数字。RANKX函数可用于创建动态的排名指标。以下是RANKX函数的基本语法示例： RANKX( , <expression>, [value], [order], [ties]) - ` `：指定用于计算排名的表格。 - `<expression>`：指定要排序的表达式。 - `[value]`：指定要计算排名的值。如果未提供，默认为当前行的值。 - `[order]`：指定排名的顺序。可以选择升序（ASC）或降序（DESC）。如果未提供，则默认为升序。 - `[ties]`：指定如何处理并列的排名。可以选择First、Last或None。如果未提供，默认为None。 以下是一个示例，演示如何使用RANKX函数计算订单金额在销售表中的排名： ``` RANKX( Sales, SUM(Sales[OrderAmount]), ,DESC, SKIP ) ``` 此示例使用Sales表中的订单金额列作为表达式，并以降序顺序进行排名。它还使用了SKIP参数， - 具体实现 - `RRRQtyRank = RANKX(all('Mapping table'[Dell Market Name],'Mapping table'[Dell Model(platform)]),[RRRQty]+[RRR_Rate],,DESC)` - 第一个参数是需要参与排序的列，或者是会被影响的排序列，可以放多个列 - 第二个参数是用于排序的值，当有些值重复可能排序会一样，我们可以考虑加入一个运算减少同样的重复 - 第四个参数是排序的顺序，就是升序降序
关联度分析理论在数据挖掘和关联规则分析中，置信度（confidence）和提升度（lift）是两个重要的指标。置信度（confidence）是指在关联规则分析中，条件A发生的情况下，事件B也发生的概率。数学上可以表示为：置信度 = P(B|A) = P(A 交 B) / P(A)其中，P(B|A)表示在A发生的情况下B发生的概率，P(A 交 B)表示A和B同时发生的概率，P(A)表示A发生的概率。置信度的取值范围在0到1之间，数值越接近1表示事件B在条件A发生时的概率越大，即关联性越强。提升度（lift）是指在发现了关联规则A->B之后，B事件发生的概率相对于其在整体样本中发生的概率提升了多少。数学上可以表示为：提升度 = 置信度 / P(B)3.支持度（support）代表在所有条件中AB同时发生的概率其中，P(B)表示B事件发生的概率。提升度的取值大于1表示A的出现对B的出现有促进作用，等于1表示A对B的出现没有影响，小于1表示A的出现对B的出现有抑制作用。在关联规则分析中，置信度和提升度可以帮助我们了解不同事件之间的关联程度和影响程度，从而进行更深入的数据挖掘和分析。DAX公式实现同时买AB = VAR TABLE1=FILTER('Sales Order',RELATED('Product'[Product])=Product_ass[LEFTITEM]) VAR TABLE2=FILTER('Sales Order',RELATED('Product'[Product])=Product_ass[RIGHTITEM]) VAR TABLE3=INTERSECT(SELECTCOLUMNS(TABLE1,"salesorder",[Sales Order]),SELECTCOLUMNS(TABLE2,"salesorder",[Sales Order])) RETURN COUNTROWS(table3) 购买A = COUNTROWS(FILTER('Sales Order',RELATED('Product'[Product])=Product_ass[LEFTITEM])) 只购买B = COUNTROWS(FILTER('Sales Order',RELATED('Product'[Product])=Product_ass[RIGHTITEM] && 'Sales Order'[ordercount]=1))支持度 = DIVIDE(Product_ass[同时买AB],DISTINCTCOUNT('Sales Order'[Sales Order])) 置信度 = DIVIDE(Product_ass[同时买AB],Product_ass[购买A]) 提升度 = DIVIDE(Product_ass[同时买AB],Product_ass[只购买B])学习思考1.intersect需要指定对应的列，否则会到时数据交集错误2.统计数据直接使用countrows即可，不需要再用calculate进行再嵌套成品
Power BI 设置散布图颜色今天在学习这个图标是发现，当调整不同的阈值时，图形中的点会随之改变颜色实现逻辑先设置两个切片器来获取相应的阈值绘制散布图还是按照正常作业流程重点在于设置一个measure去获取切片器的值并返回相应的颜色。在散布图中的marker->color 里面设置动态的颜色值具体设置阈值使用参数来设定这里可以设置一个序列，包含初始结束值以及步长，默认值设置度量值去返回相应的颜色这个度量值用于获取两个参数设定的值，同时去与图形中每个点进行比较。然后根据比较的结果返回相应的色值P4-散点着色 = var a = SELECTEDVALUE('参数-销售额阈值'[参数-销售额阈值]) var b = SELECTEDVALUE('参数-利润阈值'[参数-利润阈值]) RETURN SWITCH(TRUE(),[销售金额]>=A&&[利润]>=B,"#BC1A27", [销售金额]>=A&&[利润]<B,"#50B127", [销售金额]<A&&[利润]<B,"#e47c41", [销售金额]<A&&[利润]>=B,"#5865B0")设置动态颜色选择field value,然后选择设定的散点着色值
powerbi新特性 字段参数字段参数字段参数可以帮助我们更好的完成动态筛选。默认的筛选可能只在某一个表格列中，而字段参数可以实现跨表格列，以及使用多度量值筛选。在Modeling里面可以选择新建参数。当参数设置完成后，会生成一个计算表。初次看这个计算表，以为是用DAX 函数 NAMEOF写的一个公式。但是实际上，是当我们新建参数时，系统自动生成的。我们可以进行二次编辑。案例学习：这个案例的研究了很久，作者的思路的确很巧妙。图形上面设置了几个slicer,包含度量值筛选，按TOP还是BOTTOM，以及排名数字，产品、catergory等进行展示。从关联上来看，下面的图表放入的数据和上方的筛选没有相应的关联关系。当我们按照同样的数值进行绘制图表，会发现上方的筛选器都是无效的。从图表的筛选上面来看，可以发现多了一个度量值的筛选。查看该度量值，可以看到，它是判定了选择TOPN还是BOTTMN，以及排名的数字是多少。然后将另外一个度量值与排名数字进行比较，如果小于排名数字就是1，否则就是0。而使用filter只选择1的部分，这样就实现了TOPN的排序功能。过滤综合指标 = var a =SELECTEDVALUE('TOPNBOTTMN'[TOPN/BOTTMN]) var b =SELECTEDVALUE('Topn'[序号]) return SWITCH(true(),a="TOPN",IF([Rank_按综合指标]<=B,1,0), a="BOTTMN",IF([Rank_按综合指标 -反序]<=B,1,0))继续展开到Rank_按综合指标这个度量值。这里的DAX逻辑是，根据选择的'参数-指标'[参数-指标 个字段]来判定界面上选择的是那个指标，然后获取对应这个指标的按照相应的分类得到的RANK排名。这样就实现了根据TOPN/BOTTOM N，进行动态排名的目的。Rank_按综合指标 = VAR xs = SWITCH(TRUE(), ISFILTERED('Product'[category]), RANKX(ALLSELECTED('Product'[category]),[销售金额]), ISFILTERED('Product'[Subcategory]), RANKX(ALLSELECTED('Product'[Subcategory]),[销售金额]), ISFILTERED('Product'[Model]),RANKX(ALLSELECTED('Product'[Model]),[销售金额]), ISFILTERED('Product'[Product]), RANKX(ALLSELECTED('Product'[Product]),[销售金额]), ISFILTERED('Product'[SKU]), RANKX(ALLSELECTED('Product'[SKU]),[销售金额]), ISFILTERED('Customer'[Customer]), RANKX(ALLSELECTED('Customer'[Customer]),[销售金额]), ISFILTERED('Reseller'[Reseller]), RANKX(ALLSELECTED('Reseller'[Reseller]),[销售金额]), ISFILTERED('Sales Territory'[Country]), RANKX(ALLSELECTED('Sales Territory'[Country]),[销售金额]), BLANK()) VAR dg = SWITCH(TRUE(), ISFILTERED('Product'[category]), RANKX(ALLSELECTED('Product'[category]),[订购数量]), ISFILTERED('Product'[Subcategory]), RANKX(ALLSELECTED('Product'[Subcategory]),[订购数量]), ISFILTERED('Product'[Model]),RANKX(ALLSELECTED('Product'[Model]),[订购数量]), ISFILTERED('Product'[Product]), RANKX(ALLSELECTED('Product'[Product]),[订购数量]), ISFILTERED('Product'[SKU]), RANKX(ALLSELECTED('Product'[SKU]),[订购数量]), ISFILTERED('Customer'[Customer]), RANKX(ALLSELECTED('Customer'[Customer]),[订购数量]), ISFILTERED('Reseller'[Reseller]), RANKX(ALLSELECTED('Reseller'[Reseller]),[订购数量]), ISFILTERED('Sales Territory'[Country]), RANKX(ALLSELECTED('Sales Territory'[Country]),[订购数量]), BLANK()) VAR cb = SWITCH(TRUE(), ISFILTERED('Product'[category]), RANKX(ALLSELECTED('Product'[category]),[成本]), ISFILTERED('Product'[Subcategory]), RANKX(ALLSELECTED('Product'[Subcategory]),[成本]), ISFILTERED('Product'[Model]),RANKX(ALLSELECTED('Product'[Model]),[成本]), ISFILTERED('Product'[Product]), RANKX(ALLSELECTED('Product'[Product]),[成本]), ISFILTERED('Product'[SKU]), RANKX(ALLSELECTED('Product'[SKU]),[成本]), ISFILTERED('Customer'[Customer]), RANKX(ALLSELECTED('Customer'[Customer]),[成本]), ISFILTERED('Reseller'[Reseller]), RANKX(ALLSELECTED('Reseller'[Reseller]),[成本]), ISFILTERED('Sales Territory'[Country]), RANKX(ALLSELECTED('Sales Territory'[Country]),[成本]), BLANK()) VAR lr = SWITCH(TRUE(), ISFILTERED('Product'[category]), RANKX(ALLSELECTED('Product'[category]),[利润]), ISFILTERED('Product'[Subcategory]), RANKX(ALLSELECTED('Product'[Subcategory]),[利润]), ISFILTERED('Product'[Model]),RANKX(ALLSELECTED('Product'[Model]),[利润]), ISFILTERED('Product'[Product]), RANKX(ALLSELECTED('Product'[Product]),[利润]), ISFILTERED('Product'[SKU]), RANKX(ALLSELECTED('Product'[SKU]),[利润]), ISFILTERED('Customer'[Customer]), RANKX(ALLSELECTED('Customer'[Customer]),[利润]), ISFILTERED('Reseller'[Reseller]), RANKX(ALLSELECTED('Reseller'[Reseller]),[利润]), ISFILTERED('Sales Territory'[Country]), RANKX(ALLSELECTED('Sales Territory'[Country]),[利润]), BLANK()) VAR kd = SWITCH(TRUE(), ISFILTERED('Product'[category]), RANKX(ALLSELECTED('Product'[category]),[客单金额]), ISFILTERED('Product'[Subcategory]), RANKX(ALLSELECTED('Product'[Subcategory]),[客单金额]), ISFILTERED('Product'[Model]),RANKX(ALLSELECTED('Product'[Model]),[客单金额]), ISFILTERED('Product'[Product]), RANKX(ALLSELECTED('Product'[Product]),[客单金额]), ISFILTERED('Product'[SKU]), RANKX(ALLSELECTED('Product'[SKU]),[客单金额]), ISFILTERED('Customer'[Customer]), RANKX(ALLSELECTED('Customer'[Customer]),[客单金额]), ISFILTERED('Reseller'[Reseller]), RANKX(ALLSELECTED('Reseller'[Reseller]),[客单金额]), ISFILTERED('Sales Territory'[Country]), RANKX(ALLSELECTED('Sales Territory'[Country]),[客单金额]), BLANK()) RETURN SWITCH(TRUE(),SELECTEDVALUE('参数-指标'[参数-指标 个字段])="'Measure'[销售金额]",xs, SELECTEDVALUE('参数-指标'[参数-指标 个字段])="'Measure'[订购数量]",dg, SELECTEDVALUE('参数-指标'[参数-指标 个字段])="'Measure'[成本]",cb, SELECTEDVALUE('参数-指标'[参数-指标 个字段])="'Measure'[利润]",lr, SELECTEDVALUE('参数-指标'[参数-指标 个字段])="'Measure'[客单金额]",kd )