FAQ > 金融建模 > 第三方交互 > R

Q:如何解决R语言4.2.0及以上版本原生支持UTF-8导致交互转码引起的异常    

  • A:R语言在4.2.0+版本上实现了对UTF-8的原生支持,但天软默认的是gbk格式,在交互过程中,若存在中文字符,则可能导致交互失败或结果异常,如:
    情景一:交互时,提交到天软服务器的脚本中存在中文字符串,由于R中为为UTF-8编码,传送到天软解析错误,导致tsl运行失败
     一般的解决办法有两种:
    方法一:将包含中文的字符串通过天软函数Utf8toansi将UTF8串转为Ansi串。
    方法二:可通过R语言中的模型iconv将UTF8串转为Ansi串后再传入天软
    情景二:交互后返回到R中的结果集中存在中文字符串时,由于源码是gbk编码,在UTF-8编码环境下,显示会存在乱码现象
     解决办法:天TSL交互语句中选通过模型AnsiToUtf8将结果集中的中文相关字符串转为UTF8格式,再返回到R中后,可以正常显示。

    特别说明:对于字符进行转码是只对中文格式输入的字符产生影响,在使用过程中可以只转换中文格式字符串

    TSL转码相关函数说明:
    FAQ:UTF8ToAnsi
    FAQ:AnsiToUTF8

    查看R编码环境方法:
    环境说明:使用64位4.2.1版的R语言与天软进行交互,默认编码环境Chinese (Simplified)_China.utf8
    可以通过代码:Sys.setlocale(category="LC_ALL",local="")设置R的默认编码环境


    R交互相关文档:
    FAQ:2014-11-17-应用专题-第三方交互06:天软平台与R交互(基于TSLR.DLL和ODBC两种方式)
    FAQ:2014-09-26-应用专题-第三方交互05:天软平台与 R 的交互

    R交互中中文转码的范例展示-中文字符串部分进行局部转换
    R调用天软有ODBC与DLL两种方式。两种方式中,同时又都支持调用tsl语句串及tsl函数。下面范例分别从这几种方式进行展示转码的一个效果:

    调用tsl函数方式:函数中将中文列名及中文字符串转成Utf8后输出
    天软中封装用户函数R_test:对中文列名“代码”以及"name"列中的数值进行转码处理
    转码模型:AnsiToUtf8
    Function R_test();
    Begin
      t:= Query("科创板","",True,"",
           AnsiToUtf8("代码"),DefaultStockID(),
           "name",CurrentStockName(),
           "firstday",StockGoMarketDate());
      t[:,"name"]:= AnsiToUtf8(t[:,"name"]);
      return t;
    End;


    范例一:ODBC交互+调天软函数
    R交互代码:
    library(RODBC)
    channel=odbcConnect("jh_test")
    sqlstr="return R_test();"
    t=sqlQuery(channel,sqlstr)
    t
    执行结果:



    范例二:DLL交互+调用天软函数的方式
    R代码:
    dyn.load("C:/program files/Tinysoft/Analyse.NET/tslr.dll")
    server=.External("tslConnectServer","tsl.tinysoft.com.cn",443,NULL)
    dl=.External("tslLoginServer","user","password")
    t=.External("tslRemoteCallFunc","R_test",NULL,NULL)
    t
    执行结果:



    调用tsl语句串方式:函数中将中文列名及中文字符串转成Utf8后输出
    交互串如下:将脚本中的中文字符串调用utf8toansi转成gbk后再运行,返回前将结果中的中文字符转成utf8后再return。

    sqlstr='t:= Query(utf8toansi("深证A股;上证A股;中小企业板;创业板;科创板"),"",True,"","代码",DefaultStockID(),"名称",CurrentStockName(),"上市日",StockGoMarketDate());t[:,"名称"]:= AnsiToUtf8(t[:,"名称"]);return t;'

    范例三:ODBC交互+tsl语句串方式
    R代码:
    library(RODBC)
    channel=odbcConnect("jh_test")
    sqlstr='t:= Query(utf8toansi("深证A股;上证A股;中小企业板;创业板;科创板"),"",True,"","代码",DefaultStockID(),"名称",CurrentStockName(),"上市日",StockGoMarketDate());t[:,"名称"]:= AnsiToUtf8(t[:,"名称"]);return t;'
    t=sqlQuery(channel,sqlstr)
    t
    执行结果:



    范例四:DLL交互+tsl语句串方式
    R代码:
    dyn.load("C:/program files/Tinysoft/Analyse.NET/tslr.dll")
    server=.External("tslConnectServer","tsl.tinysoft.com.cn",443,NULL)
    dl=.External("tslLoginServer","user","password")
    sqlstr='t:=Query(utf8toansi("深证A股;上证A股;创业板;科创板"),"",True,"","代码",DefaultStockID(),"名称",CurrentStockName(),"上市日",StockGoMarketDate());t[:,"名称"]:= AnsiToUtf8(t[:,"名称"]);return t;'
    t=.External("tslRemoteExecute",sqlstr,list())
    t[[2]][[10]]
    执行结果:



    从上面对比可以看出,不管是odbc方式还是dll方式,转换的过程是一样的。所以,下面的范例中,以ODBC方式为例,对常见的场景进行举例展示:

    R交互中中文转码的范例展示-批量转码
    在实际交互取数中往会存在多列数据需要转换的情况,可以使用矩阵遍历模型做全量转换
    注意:转码是针对字符串格式数据做转化,转换模型只支持字符串格式数据
    参考
    FAQ:::与::=的应用举例
    FAQ:?:判断求值三元运算符

    范例五:对返回结果集做全量转码
    R代码:
    library(RODBC)
    channel <- odbcConnect("tsodbc")
    sqlstr <- paste0('
    t := Query(utf8toansi("深证A股;上证A股;创业板;科创板;北证A股"),"",True,"",
    "代码",DefaultStockID(),
    "名称",CurrentStockName(),
    "截止日",report(40000,20231231),
    "公布日",report(40001,20231231),
    "预警内容",report(40003,20231231),
    "预警类型",report(40002,20231231));
    t ::= ifstring(mcell) ? ansitoutf8(mcell) : mcell;
    return t;
    ')
    t <- sqlQuery(channel,sqlstr)
    print(tail(t,5))
    执行结果:


    转换列名
    部分天软模型返回的列名带有中文格式的需要进行转换
    参考:FAQ:Q:如何修改数组的列名(列下标)

    范例六:所有列名进行全量转码处理
    R代码
    library(RODBC)
    channel <- odbcConnect("tsodbc")
    sqlstr <- '
    GetBkWeightByDate("SH000300",20230116T,t);
    t ::= ifstring(mcell) ? ansitoutf8(mcell) : mcell;
    //批量替换列名
    names:=ansitoutf8(mcols(t,1));
    t1:=Zeros(mrows(t),names);
    t1[:,:]:=t;

    return t1;'
    xxx <- sqlQuery(channel,sqlstr)
    print(xxx)
    执行结果:



    范例七:对指定列名进行转码显示
    R语言
    library(RODBC)
    channel <- odbcConnect("tsodbc")
    sqlstr <- '
    SetSysParam("BegT",20240115t);
    SetSysParam("EndT",20240116t);
    t := QueryWithPeriod("","SH000001",@True,"","最高价",@high(),
      "最低价",@low(),
      "涨幅(%)",@StockZf3(),
      "收盘价",@close(),
      "开盘价",@open(),
      "成交量",@vol(),
      "成交金额",@amount(),
      "成交比数",@tradecount());
    //模型中默认返回两个中文名称列,需要转换
    reindex(t,nil,array(Utf8ToAnsi("代码"):"代码",Utf8ToAnsi("名称"):"名称"));
    t ::= ifstring(mcell) ? ansitoutf8(mcell) : mcell;
    return t;'
    xxx <- sqlQuery(channel,sqlstr)
    print(xxx)
    执行结果: