• Archive by category "R语言实践"
  • (Page 3)

Blog Archives

用R语言实现汉明距离算法Hamming Distance

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

转载请注明出处:
http://blog.fens.me/r-hamming-distance/

前言

在文字处理时,经常会用到编码方式,把文字和数字进行编码转换,从而计算文本的相似性。比如英文,差一个字母,字母的顺序写反了。要实现对文字的模糊匹配,就可以用到汉明距离的思路,计算将一个字符串变换成另外一个字符串所需要替换的字符个数。

目录

  1. 汉明距离介绍
  2. 算法原理
  3. R语言代码实现

1. 汉明距离介绍 Hamming Distance

Hamming Distance汉明距离,是以理查德·卫斯里·汉明的名字命名的。在信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。汉明距离的计算思路与莱文斯坦距离算法有类似之处,参考文章R语言莱文斯坦距离算法Levenshtein Distance

汉明距离计算,例如:

  • 二进制 1011101 与 1001001 之间的汉明距离是 2。
  • 字符串 2143896 与 2233796 之间的汉明距离是 3。
  • 字符串 toned 与 roses 之间的汉明距离是 3。

汉明重量,是字符串相对于同样长度的零字符串的汉明距离,也就是说,它是字符串中非零的元素个数:对于二进制字符串来说,就是 1 的个数,所以 1110001 的汉明重量是 4。

2. 算法原理

我们以d(x,y)表示两个数字x,y之间的汉明距离。

  • 对于两个等长字符串,可直接进行两个字符串对应位置的不同字符的个数。
  • 对于两个数字,可先转为二进制,然后进行异或运算,并统计结果为1的个数。

两个二进制组(00)与(01)的距离是1,(110)和(101)的距离是2。在一个码组集合中,任意两个编码之间汉明距离的最小值称为这个码组的最小汉明距离。最小汉明距离越大,码组越具有抗干扰能力。

例如,2个数字93和73,93的二进制为10001001,73的二进制为10110001,然后进行xor异或运算,结果为10100,对结果统计1的个数,即得到汉明距离为2。

3. R语言实现

3.1 字符串类型

针对字符串的建立汉明距离算法,计算汉明距离。


> haming_string<-function(txt1,txt2){
+   len1<-nchar(txt1)
+   len2<-nchar(txt2)
+   
+   if(len1!=len2){
+     stop(paste("length is not equal"))
+   }
+   
+   n<-0
+   for(i in 1:len1){
+     t1<-substring(txt1,i,i)
+     t2<-substring(txt2,i,i)
+     if(t1!=t2){
+       n<-n+1
+     }
+   }
+   return(n)
+ }

汉明距离测试。


> haming_string("1011101","1101001")
[1] 3
> haming_string("2143896","2233796")
[1] 3
> haming_string("toned","roses")
[1] 3

3.2 数字类型
针对数字的建立汉明距离算法,先转换为二进制,再进行异或计算,计算汉明距离。


> haming_int<-function(num1,num2){
+   b1<-intToBits(num1)
+   b2<-intToBits(num2)
+   x<-xor(b1,b2);x
+   length(which(x==1))
+ }

汉明距离测试。


> haming_int(93,73)
[1] 2
> haming_int(137,177)
[1] 3

本文我们了解汉明距离的原理和实现,后面我们就可以利用汉明距离的特性,对字符串和数字进行相似度的距离计算,从而实现文本的模糊匹配。本文代码:https://github.com/bsspirit/r-string-match/blob/main/hanmming.r

转载请注明出处:
http://blog.fens.me/r-hamming-distance/

打赏作者

R语言莱文斯坦距离算法Levenshtein Distance

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

转载请注明出处:
http://blog.fens.me/r-levenshtein-distance/

前言

文字模糊匹配,是在文字处理时,要常用到的一种功能。比如英文,差一个字母,字母的顺序写反了。要实现对文字的模糊匹配,就可以用到莱文斯坦距离的思路,将一个字符串变为另一个字符串需要进行编辑操作最少的次数。

输入法的拼写检查,纠正用户输入的拼写错误,就是使用到了莱文斯坦距离。

目录

  1. 莱文斯坦距离介绍
  2. 算法原理
  3. R语言代码实现
  4. adist()函数调用

1. 莱文斯坦距离介绍 Levenshtein Distance

Levenshtein Distance莱文斯坦距离,属于编辑距离的一种,主要用于衡量两个字符串之间的差异。由苏联数学家Vladimir Levenshtein于1965年提出,被广泛应用于拼写纠错检查、DNA分析、语音识别等领域。

两个字符串之间的Levenshtein Distance莱文斯坦距离指的是,将一个字符串变为另一个字符串需要进行编辑操作最少的次数。其中,允许的编辑操作有以下三种,替换、插入、删除。

  • 「替换」:将一个字符替换成另一个字符
  • 「插入」:插入一个字符
  • 「删除」:删除一个字符

例如,计算 house 到 rose 的莱文斯坦距离。

第一步:house 把第一位 h 替换为 r,得到rouse。
第二步:rouse 把第三位 u 删除,得到rose

即完成了计算,莱文斯坦距离为2.

2. 算法原理

对于两个字符串A、B而言,字符串A的前i个字符和字符串B的前j个字符的莱文斯坦距离符合如下公式。

在数学上,两个字符串a,b的莱文斯坦距离:

计算公式:

表示内容:

2.1 第一种情况:当至少存在一个字符串为空串

若字符串A是一个长度为0的空字符串时,则其变为长度为n的字符串B。只需对字符串A进行n次插入操作即可。

例如:


A="",B="abc"时
lev距离 = max(length(A),length(B)) = max(0,3) = 3

同理,若字符串A是一个长度为n的字符串时,则其变为长度为0的空字符串B。则只需对字符串A进行n次删除操作即可。

例如:


A="abcd",B=""时
lev距离 = max(length(A),length(B)) = max(4,0) = 4

故在上述公式中,可将这两种情况统一为: 当两个字符串的长度最小值为0时,则说明有一个字符串为空串。则这二者之间的莱文斯坦距离为两个字符串长度的最大值。

2.2 第二种情况:两个字符串均不为空串

当两个字符串均不为空串时,这里假设字符串A为horse、字符串B为ros。由于替换/插入/删除,三种操作不会改变字符串中各字符的相对顺序。因此,可以每次仅对字符串A进行操作,即只考虑
字符串A的前i个字符 和 字符串B的前j个字符 的莱文斯坦距离,让i和j都从1开始计数。字符串A的前5个字符 和 字符串B的前3个字符 的莱文斯坦距离lev(5,3),就是最终我们所求的字符串A、字符串B之间的莱文斯坦距离3。

【插入】假设我们把 horse 变为 ro 的莱文斯坦距离记为u,即:


# 字符串A的前5个字符 和 字符串B的前3个字符 的莱文斯坦距离为 u
lev(5,2) = u

则 horse 期望变为 ros,其所需的编辑次数不会超过 u+1。因为 horse 只需先经过u次编辑操作变为 ro,然后在尾部插入s字符即可变为 ros

【删除】假设我们把 hors 变为 ros 的莱文斯坦距离记为v,即:


# 字符串A的前4个字符 和 字符串B的前3个字符 的莱文斯坦距离为 v
lev(4,3) = v

则 horse 期望变为 ros,其所需的编辑次数不会超过 v+1。因为 horse 只需先进行一次删除操作变为 hors,再经过v次编辑操作即可变为 ros

【替换】假设我们把 hors 变为 ro 的莱文斯坦距离记为w,即


# 字符串A的前4个字符 和 字符串B的前2个字符 的莱文斯坦距离为 w
lev(4,2) = w

则 horse 期望变为 ros,其所需的编辑次数不会超过 w+1。因为 horse 只经过w次编辑操作即可变为 roe,然后通过一次替换操作,将尾部的e字符替换为s字符即可。

得出莱文斯坦距离满足如下的递推公式


lev(horse, ros) = lev(5,3)
= min( lev(5,2)+1, lev(4,3)+1, lev(4,2)+1 )
= min(u+1, v+1, w+1)

如果 某字符串A的第i个字符 与 某字符串B的第j个字符 完全相同,则其所需的编辑次数肯定不会超过 lev(i-1, j-1)。因为无需进行替换,可跳过该步骤。

通过上面的分析过程,我们其实不难看出。如果期望 字符串A的前i个字符 与 字符串B的前j个字符 完全相同。可以有如下三种途径操作方式进行实现。而最终的莱文斯坦距离就是下面三种实现方式中次数最小的一个。

  1. 在 字符串A的前i个字符 与 字符串B的前j-1个字符 完全相同的基础上,进行一次「插入」操作
  2. 在 字符串A的前i-1个字符 与 字符串B的前j个字符 完全相同的基础上,进行一次「删除」操作
  3. 在 字符串A的前i-1个字符 与 字符串B的前j-1个字符 完全相同的基础上,如果字符串A的第i个字符与字符串B的第j个字符不同,则需要进行一次「替换」操作;如果字符串A的第i个字符与字符串B的第j个字符相同,则无需进行任何操作。

参考文章:https://zhuanlan.zhihu.com/p/507830576

3. R语言代码实现

构建lev_dist()函数,实现莱文斯坦距离,使用递归方法进行实现。想了一种简单的实现方法,但效率太低,看看就好,千万不要用到实际的算法中。等有时间,我再换个思路实现一下。


#######################################
# Levenshtein 莱文斯坦距离,递归实现(效率很低)
######################################
> lev_dist<-function(txt1,txt2){
+   len1<-nchar(txt1)
+   len2<-nchar(txt2)
+   
+   if(len1==0) return(len2)
+   if(len2==0) return(len1)
+   
+   # 插入消耗
+   insert_cost <- lev_dist(txt1, substring(txt2,1,len2-1)) + 1;
+   
+   # 删除消耗
+   delete_cost <- lev_dist(substring(txt1,1,len1-1), txt2) + 1;
+   
+   # 替换消耗
+   cost<-ifelse(substring(txt1,len1,len1) == substring(txt2,len2,len2),0,1)
+   replaces_cost <- lev_dist(substring(txt1,1,len1-1), substring(txt2,1,len2-1)) + cost;
+   
+   rs<-min(insert_cost,delete_cost,replaces_cost)
+   print(paste("txt1:",txt1,"txt2:",txt2,"insert:",insert_cost,"delete:",delete_cost,"replaces:",replaces_cost))
+   return(rs)
+ }

对结果进行测试


# 测试ab和a的情况
> lev_dist("ab","a")
[1] "txt1: a txt2: a insert: 2 delete: 2 replaces: 0"
[1] "txt1: ab txt2: a insert: 3 delete: 1 replaces: 2"
[1] 1

# 测试ab和abc的情况
> lev_dist("ab","abc")
[1] "txt1: a txt2: a insert: 2 delete: 2 replaces: 0"
[1] "txt1: ab txt2: a insert: 3 delete: 1 replaces: 2"
[1] "txt1: a txt2: a insert: 2 delete: 2 replaces: 0"
[1] "txt1: a txt2: ab insert: 1 delete: 3 replaces: 2"
[1] "txt1: a txt2: a insert: 2 delete: 2 replaces: 0"
[1] "txt1: ab txt2: ab insert: 2 delete: 2 replaces: 0"
[1] "txt1: a txt2: a insert: 2 delete: 2 replaces: 0"
[1] "txt1: a txt2: ab insert: 1 delete: 3 replaces: 2"
[1] "txt1: a txt2: abc insert: 2 delete: 4 replaces: 3"
[1] "txt1: a txt2: a insert: 2 delete: 2 replaces: 0"
[1] "txt1: a txt2: ab insert: 1 delete: 3 replaces: 2"
[1] "txt1: ab txt2: abc insert: 1 delete: 3 replaces: 2"
[1] 1

让单词变长,虽然莱文斯坦距离并不大,但是计算次数是相当的多,效率非常低。


> lev_dist("kitten","sitting")
....
....
// 省略
3

用递归的方式,虽然比较容易实现,但是效率太低,没有办法是应用中使用。

4. adist()函数

在R的基础包utils中,找到了 adist()函数,就实现了莱文斯坦距离,我们可以直接使用adist()来完成,莱文斯坦距离的计算。还是R语言原生的程序效率高!!

分别测试 house 到 rose,horse 到 ros的 莱文斯坦距离。


# 
> adist("house","rose")
     [,1]
[1,]    2
> adist("horse","ros")
     [,1]
[1,]    3

查看替换sub 、插入ins 、删除del ,分别使用了几次。


> drop(attr(adist("horse", "rose", counts = TRUE), "counts"))
ins del sub 
  0   1   1 

按顺序查看替换、插入、删除的操作步骤,S=替换,M为跳过,D为删除,I为插入
> attr(adist("horse", "rosxeee", counts = TRUE), "trafos")
     [,1]      
[1,] "SMDMIIIM"

本文我们了解了莱文斯坦距离的原理和实现,后面我们就可以利用莱文斯坦距离的特性,对文字进行相似度的距离计算,从而实现文本的模糊匹配。本文代码:https://github.com/bsspirit/r-string-match/blob/main/levenshtein.r

转载请注明出处:
http://blog.fens.me/r-levenshtein-distance/

打赏作者

用R语言实现字符串快速匹配算法KMP

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

转载请注明出处:
http://blog.fens.me/r-kmp/

前言

文字匹配是字符符处理操作时,最常用到的一种方法。比如我们想从一段长文本中,找到是否有我想要的词,可以用于在图书中用关键词进行搜索,这样就可以定位到具体的位置。当文本长度巨大,且匹配字符串长度过长时,这种匹配就会有效率问题,很变的很慢。

那么我们可以用KMP的算法思路,在提升文字精确匹配的效率。本文代码:https://github.com/bsspirit/r-string-match

目录

  1. 字符串匹配:暴力破解法
  2. KMP算法解释和实现
  3. KMP和暴力破解算法对比

1. 字符串匹配:暴力破解法

一般的字符串匹配算法,是将 2个字符串每个字符挨个进行比较,相当于是把每个字符都比较了一遍,做了对所有字符的组合,这样操作导致的时间复杂度是O(m*n),也就是 2 个字符串长度的积,俗称暴力解法。

我们设定原始字符串为:ABDABDZ ABCED,匹配字符串为:ABC。直接使用暴力法进行字符串匹配。

首先,建立暴力破解的字符串匹配函数bad_match(),包括4个参数。

  • txt,原始文本的字符串
  • pattern,匹配的字符串
  • n,用于取匹配前几个,默认为0,表示全匹配
  • LOGGER,用于显示日志

# 清空环境变量
> rm(list=ls())

# 设置运行目录
> setwd("C:/work/R/text")

# 建立字符串匹配函数:暴力破解法
> # 暴力破解法
> baoli_match<-function(txt,pattern,n=0,LOGGER=FALSE){
+   rs<-data.frame(start=0,end=0)  # 默认返回值
+   start<-0                       # 命中后在原始字符串的开始位置
+   
+   n1<-nchar(txt)                 # 原始字符串长度
+   n2<-nchar(pattern)             # 匹配的字符串长度
+   
+   # 如果匹配的字符串为空,则返回
+   if(n2==0) return(r2)          
+   
+   # 初始化变量索引,i用于原始字符串,j用于匹配字符串
+   i<-j<-1
+   # 用于计数,循环了多少次
+   k<-0
+   
+   # 循环计算
+   while(i < n1){
+     
+     # 打印日志
+     if(LOGGER){  
+       print(paste(i,j,substr(txt, i, i),substr(pattern, j, j),sep=","))  
+       k<-k+1
+     }
+     
+     # 匹配成功,同时移动
+     if(substr(txt,i,i) == substr(pattern,j,j)){ 
+       i<-i+1
+       j<-j+1
+     } else { # 匹配不成功,回到开始匹配的位置,重置i,j的索引
+       i<-i-(j-1)  
+       i<-i+1
+       j<-1
+     }
+     
+     # 把匹配到的,所有结果存到变量
+     if(j==(n2+1)) {
+       start<-append(start,i-n2)
+       j<-1
+       
+       # 只取前面n个结果返回
+       if(n > 0 && n==length(start)-1){
+         break;
+       }
+     }
+   }
+   
+   # 打印日志,输出循环了多少次
+   if(LOGGER){
+     print(paste("k",k,sep="="))
+   }
+   
+   # 拼接返回值,为data.frame
+   if(length(start) > 1) {
+     start<-start[-1]
+     rs<-data.frame(start=start,end=start+n2-1)
+   }
+   return(rs)
+ }

输出字符串,运行结果。


# 原始字符串
> txt<-"ABCCADZABCCABBC"

# 匹配字符串
> pattern<-"ABCCABB"

# 暴力匹配
> baoli_match(txt,pattern,LOGGER=TRUE)
[1] "1,1,A,A"
[1] "2,2,B,B"
[1] "3,3,C,C"
[1] "4,4,C,C"
[1] "5,5,A,A"
[1] "6,6,D,B"
[1] "2,1,B,A"
[1] "3,1,C,A"
[1] "4,1,C,A"
[1] "5,1,A,A"
[1] "6,2,D,B"
[1] "6,1,D,A"
[1] "7,1,Z,A"
[1] "8,1,A,A"
[1] "9,2,B,B"
[1] "10,3,C,C"
[1] "11,4,C,C"
[1] "12,5,A,A"
[1] "13,6,B,B"
[1] "14,7,B,B"

# 循环共20次
[1] "k=20"
     
# 匹配到1个结果,对应用到原始字符串的开始位置和结束位置
  start end
1     8  14

2. KMP算法介绍

KMP 算法是一种改进的字符串匹配算法,由 D.E.Knuth,J.H.Morris 和 V.R.Pratt 提出的,因此人们称它为 Knuth-Morris-Pratt算法(简称KMP)。KMP 算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个 kmp_next () 函数实现,函数本身包含了模式串的局部匹配信息。KMP 算法的时间复杂度O(m+n)。

建立kmp_next() 函数,匹配字符串的最长公串。


# 建立匹配字符串的最长公串
> kmp_next <- function(patten,LOGGER=FALSE) {
+   n <- nchar(patten)
+   nxt <- rep(0, n)
+   i <- 2
+   j <- 1
+   while (i < n) {
+     if(LOGGER){
+       print(paste(i,j,substr(patten, i, i),substr(patten, j, j),sep=","))  
+     }
+     if (substr(patten, i, i) == substr(patten, j, j)) {
+       nxt[i] <- j
+       i = i + 1
+       j = j + 1
+     } else{
+       if (j > 1) {
+         j = nxt[j - 1]
+       }
+       else{
+         nxt[i] = 0
+         i = i + 1
+       }
+     }
+   }
+   nxt
+ }

运行计算结果,ABC的最长公串为0,ABCCABB最长公串,为1和2。


> kmp_next("ABC")
[1] 0 0 0

> kmp_next("ABCCABB")
[1] 0 0 0 0 1 2 0

建立KMP算法函数,使用kmp_next()最长公串的结果,减少循环的次数。


> kmp_match<-function(txt, patten, n=0, LOGGER=FALSE) {
+   rs<-data.frame(start=0,end=0)  # 默认返回值
+   start<-0                       # 命中后在原始字符串的开始位置
+   n1<-nchar(txt)                 # 原始字符串长度
+   n2<-nchar(pattern)             # 匹配的字符串长度
+   
+   # 如果匹配的字符串为空,则返回
+   if(n2==0) return(rs)
+   
+   nxt<-kmp_next(patten)       #获取next最长公串
+ 
+   # 初始化变量索引,i用于原始字符串,j用于匹配字符串
+   i<-j<-1
+   # 用于计数,循环了多少次
+   k<-0
+   
+   # 循环计算
+   while(i1) j<-nxt[j-1]+1
+       else i<-i+1
+     }
+     
+     if(j==(n2+1)) {
+       start<-append(start,i-n2)
+       j<-1
+       
+       if(n>0 && n==length(start)-1){
+         break;
+       }
+     }
+   }
+   
+   # 打印日志,输出循环了多少次
+   if(LOGGER){
+     print(paste("k",k,sep="="))
+   }
+   
+   # 拼接返回值,为data.frame
+   if(length(start)>1) {
+     start<-start[-1]
+     rs<-data.frame(start=start,end=start+n2-1)
+   }
+   return(rs)
+ }

运行KMP算法,使用暴力破解法同样的参数,发现循环计算只运行了14次,比暴力破解法少了2次。


> txt<-"ABCCADZABCCABBC"
> pattern<-"ABCCABB"

> kmp_match(txt,pattern,LOGGER=TRUE)
[1] "pattern:ABCCABB,next:0000120"
[1] "1,1,A,A"
[1] "2,2,B,B"
[1] "3,3,C,C"
[1] "4,4,C,C"
[1] "5,5,A,A"
[1] "6,6,D,B"
[1] "6,2,D,B"
[1] "6,1,D,A"
[1] "7,1,Z,A"
[1] "8,1,A,A"
[1] "9,2,B,B"
[1] "10,3,C,C"
[1] "11,4,C,C"
[1] "12,5,A,A"
[1] "13,6,B,B"
[1] "14,7,B,B"

# 循环共16次
[1] "k=16"

# 匹配到1个结果,对应用到原始字符串的开始位置和结束位置
  start end
1     8  14

3. KMP和暴力破解算法对比

我们对比一下暴力破解法 和 KMP算法,具体的差异在什么问题,为什么能少算4次。

从下面循环对比的图中,我们可以明确的看到KMP算法,少的原因在于出现的匹配不一致时,暴力匹配是让匹配字符串回到1重新开始匹配,而KMP算法则是利用了next的最大公共串,找到上一个公共串的位置,这样就可以大幅提升遍历的效率。

KMP算法的原理的参考文献:阮一峰:字符串匹配的KMP算法

虽然R语言不擅长写算法,且while循环的性能也不高,但是如果能大幅减少循环的计算次数,也是一种不错的解决方案。自己写了一套字符串匹配的代码已经放到了github:https://github.com/bsspirit/r-string-match

一点一点的优化,从算法层搞起。

转载请注明出处:
http://blog.fens.me/r-kmp/

打赏作者

用R语言把汉字转拼音pinyin

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

转载请注明出处:
http://blog.fens.me/r-pinyin/

前言

在做中文文字处理的时候,我们经常需要把中文转换成拼音,正巧看到R语言中有一个汉字转换成拼音包叫pinyin,试了一下,用起来非常轻巧。

目录

  1. pinyin包介绍
  2. 一分钟快速使用
  3. pinyin代码结构
  4. 查看汉字与拼音的字典文件
  5. 自定义字典文件

1. pinyin包介绍

这个 R 语言包粗暴地用拼音取名为 pinyin,作用是把汉字转换成拼音。从 v1.1.3 开始,增加了将汉字转换成四角号码或五笔字型的功能。从 v1.1.4 开始,用户可以指定自己的字典,随意转换。pinyin项目,核心就是把中文汉字与对应的拼音字典做了映射。

该包的作者为赵鹏博士,环境科学、大气科学专业,西交利物浦大学(苏州)健康与环境科学系助理教授,英国利物浦大学荣誉学术成员,英国高等教育学会会员,博客地址。

本文使用的R的版本为R version 4.2.3,pinyin包的版本1.1.6。

pinyin包,安装过程很简单。


# 安装
> install.packages("pinyin")

# 加载
> library(pinyin)

pinyin包的项目地址:https://github.com/pzhaonet/pinyin

2. 一分钟快速使用

pinyin包使用起来非常简单,一行代码就能完成文字向拼音的转换。py()是该项目的主函数。

通过一行代码,一个函数就能使用中文汉字转拼音,默认参数的拼音带声调,默认字典为pinyin。


> py("中文")
       中文 
"zhōnɡ_wén" 

写一个句子,再试试。


> py("现在我们正处于大数据时代")
                         现在我们正处于大数据时代 
"xiàn_zài_wǒ_men_zhēnɡ_chǔ_wéi_dà_shǔ_jū_shí_dài" 

换一个字典试试,使用pinyin2字典。


> py("中文", dic = pydic(dic = c("pinyin2")))
         中文 
"zhong1_wen2" 

声调处理,使用pydic()函数的method方法,可以改变声调的显示结果。

  • method = ‘quanpin’,标准的全拼 (默认)
  • method = ‘tone’,以数字表示声调
  • method = ‘toneless’,不含声调

# 标准的全拼 
> py("中文", dic = pydic(dic = c("pinyin"),method="quanpin"))
       中文 
"zhōnɡ_wén" 

# 数字表示声调
> py("中文", dic = pydic(dic = c("pinyin"),method="tone"))
         中文 
"zhong1_wen2" 

# 不含声调
> py("中文", dic = pydic(dic = c("pinyin"),method="toneless"))
       中文 
"zhong_wen" 

仅保留首字母,使用only_first_letter参数TRUE。


> py('中文', dic = pydic(dic = c("pinyin"),only_first_letter = TRUE))
 中文 
"z_w"

字符串转换,把字符串里边包含非汉字字符,使用other_replace参数,转换成指定字符@。


> py('中文abc', other_replace="@",dic = pydic(dic = c("pinyin")))
          中文abc 
"zhōnɡ_wén_@_@_@" 

去掉下划线分隔符,或者改变分隔符号,使用sep参数。


> py("中文", sep="" ,dic = pydic(dic = c("pinyin")))
      中文 
"zhōnɡwén" 

> py("中文", sep="", dic = pydic(dic = c("pinyin"),method="toneless"))
      中文 
"zhongwen" 

# 用空格为分隔符
> py("中文", sep=" ", dic = pydic(dic = c("pinyin"),method="toneless"))
       中文 
"zhong wen" 

多词的转换


> library(magrittr)

> py(c("中文","英文","法文"))
       中文        英文        法文 
"zhōnɡ_wén"  "yānɡ_wén"    "fǎ_wén" 

# 多词拼接成一个字符串
> py(c("中文","英文","法文")) %>% paste(collapse = ",")
[1] "zhōnɡ_wén,yānɡ_wén,fǎ_wén"

3. pinyin包的代码结构

打开 pinyin 包的帮助文件,可以看到一共有11函数。

  • py():主函数入口,支持输入一段文字
  • py_single():单个文字转拼音,被py()循环进行调用/li>
  • pydic():字典函数参数配置
  • load_dic():加载字典文件
  • file.rename2py(): 将目录中,文件名的汉字转换成拼音
  • file2py:将目录中,文件的汉字转换成拼音
  • bookdown2py: 是专门为 bookdown 包服务的,作用是为章节的中文标题自动添加个对应的拼音ID {#biaotipinyin}
  • pinyin():已经不用

pinyin包中的,py()函数是这个包中入门函数,用于加载字符串。然后,把字符串拆解以单个文字传入py_single()函数,进行拼音转换。通过load_dic() 加载字典文件,pydic() 设置参数,用于声调输出样式。

4. 查看汉字与拼音的字典文件

在pinyin包中,预置了2个字典文件,用于把中文汉字和拼音的对应关系进行映射。

查看当前汉字与拼音的字典,找到pinyin项目在本地的安装位置,找到字典文件。

找到字典文件。


> path<- "C:/Users/bsspi/AppData/Local/R/win-library/4.2/pinyin/lib"
> dir(path)
[1] "pinyin.txt"  "pinyin2.txt"

查看字典文件pinyin.txt。


> zidian1<-readLines(paste(path,"pinyin.txt",sep="/"))
> head(zidian1,20)
 [1] "# source: http://bbs.unispim.com/forum.php?mod=viewthread&tid=31644CJK "
 [2] "# format = 1"                                                           
 [3] "㐀 qiū(qiu1)"                                                           
 [4] "㐁 tiàn(tian4)"                                                         
 [5] "㐄 kuà(kua4)"                                                           
 [6] "㐅 wǔ(wu3)"                                                             
 [7] "㐆 yǐn(yin3)"                                                           
 [8] "㐌 yí(yi2)"                                                             
 [9] "㐖 xié(xie2)"                                                           
[10] "㐜 chóu(chou2)"                                                         
[11] "㐡 nuò(nuo4)"                                                           
[12] "㐤 dān qiú(dan1 qiu2)"                                                  
[13] "㐨 xù(xu4)"                                                             
[14] "㐩 xíng(xing2)"                                                         
[15] "㐫 xiōng(xiong1)"                                                       
[16] "㐬 liú(liu2)"                                                           
[17] "㐭 lǐn(lin3)"                                                           
[18] "㐮 xiānɡ(xiang1)"                                                       
[19] "㐯 yōng(yong1)"                                                         
[20] "㐰 xìn(xin4)"                                                           

查看字典文件pinyin2.txt。


> zidian2<-readLines(paste(path,"pinyin2.txt",sep="/"))
> head(zidian2,20)
 [1] "# source:"       "# format = 1"    "丂 yu2 kao3"    
 [4] "丄 shang4"       "丅 xia4"         "丆 shi2"        
 [7] "丏 mian3"        "丗 shi4"         "丟 diu1"        
[10] "丠 qiu1"         "両 liang3"       "丣 you3"        
[13] "並 bing4"        "丩 jiu1"         "丮 ji3"         
[16] "丯 jie4"         "丱 kuang4 guan4" "丳 chan3"       
[19] "丵 zhuo2"        "丷 ba1"  

5. 自定义字典文件

使用load_dic()载入自定义字典时,目前有三个可用字典:

  • 四角号码字典:https://github.com/pzhaonet/pinyin/raw/master/inst2/sijiao.txt
  • 五笔 98:https://github.com/pzhaonet/pinyin/raw/master/inst2/wubi98.txt
  • 五笔 86:https://github.com/pzhaonet/pinyin/raw/master/inst2/wubi86.txt

我们可以从网上下载这3个文件,放到本地的目录中。

加载四角号码字典,并进行转换。


> dic_sj<-load_dic(paste(path,"sijiao.txt",sep="/"))
Warning messages:
1: In type.convert.default(X[[i]], ...) :
  'as.is' should be specified by the caller; using TRUE
2: In type.convert.default(X[[i]], ...) :
  'as.is' should be specified by the caller; using TRUE
> py("中文", dic = dic_sj)
       中文 
"50006_400" 

加五笔字典,并进行转换。


> dic_wubi86<-load_dic(paste(path,"wubi86.txt",sep="/"))
> py("中文", dic = dic_wubi86)
      中文 
"khk_yygy" 

> dic_wubi98<-load_dic(paste(path,"wubi98.txt",sep="/"))
> py("中文", dic = dic_wubi98)
      中文 
"khk_yygy" 

这样就完成了对pinyin工具的使用,很小很方便。不仅可以完成中文转拼音,还能通过自定义的字典功能实现,各种基于中文文字的转换。

pinyin项目,核心就是把中文汉字与对应的拼音字典做了映射,技术难度虽然不大,但有了这样的工具确实方便了很多。当然,除了这个工具像tmcn包,也用转换拼音的函数。给作者点个赞!

转载请注明出处:
http://blog.fens.me/r-pinyin/

打赏作者

2023 第16届中国R会议暨 2023X-AGI 大会: 面向落地的数据分析

跨界知识聚会系列文章,“知识是用来分享和传承的”,各种会议、论坛、沙龙都是分享知识的绝佳场所。我也有幸作为演讲嘉宾参加了一些国内的大型会议,向大家展示我所做的一些成果。从听众到演讲感觉是不一样的,把知识分享出来,你才能收获更多。

关于作者

转载请注明出处:
http://blog.fens.me/meeting-r-agi-20231125


前言

每年一度的R语言大会,2023年也如期而至。本次会议同步开展线下会场和线上会场共20个会场,共包含六十余精彩的演讲。会场演讲嘉宾包括学界杰出代表、业界大咖等。众多分会场,包罗万象,覆盖了AI的方方面面。分会场:Keynote,Al+ 医疗,Al+ 金融,计算平台,大模型 infra,具身智能, AI4Math, 大模型产业实践-1,大模型产业实践-2,大模型 +Agent,自动驾驶,数据科学理论,生物统计-1,AI 基础理论,生物统计-2,统计计算与软件,可信Al,AI 4 社会科学,强化学习,Al+ 可视化。涵盖了数据科学的各个领域,讨论了数据科学在诸多领域的最新进展。

我在大模型产业实践专场-2专场,有幸和3位行业专家一起进行分享。

目录

  1. 我分享的主题:面向落地的数据分析
  2. 会议体验和照片分享

1. 我分享的主题:面向落地的数据分析

现在我们正处于大数据时代,处处都产生数据,大部分数据已经不在稀缺,分析方法和算法模型都也写在了教课书中。如何挖掘出数据的价值,让数据分析落地,把数据价值转换为自身价值,是数据分析师核心要考虑的。

数据分析要解决实际业务场景问题,伪需求、不清晰的目标,都会造成项目失败。数据分析不只是指标体系、更不是指标堆积,市场在变,数据也在变,我们的知识结构也要跟着变化。数据分析是跨学科的工作,对人的要求也越来越高,调包侠的时代已过。要以新的视角,看数据、看业务、看技术发展、看我们自己,适应变化,才能把项目做好、落地。

以我多年的对数据分析的实际经验,借助R语言让“可能”变成“可行”。

本次分享的PPT:面向落地的数据分析

我主要为分四个部分进行介绍:

  • 什么是数据落地
  • 数据分析怎么做
  • 调包侠的时代已过
  • 企业需要什么样的人

2. 会议体验和照片分享

大会官方主页:https://china-r.cosx.org/bj2023/index.html

大会官方会议纪要:https://mp.weixin.qq.com/s/ELhd28tx1A6lkUl6XOOF9g

本次会议官方报名页:https://mp.weixin.qq.com/s/l_9yqRI16dl4djD-svWRYw

各个分会场主题和嘉宾。

2.1 会议主题

在大模型产业实践专场-2专场活动,由 4位行业专家参加:姚凯、殷磊、张丹、高天辰 一起作为分享嘉宾。本场的视频回看:https://www.bilibili.com/video/BV1Aj411L79K/

姚凯,主题:人工智能时代调研如何智能化。

姚凯,中央财经大学商学院副教授,Credamo见数创始人,博士毕业于北大光华管理学院营销建模方向,美国宾大沃顿商学院联合培养博士,本科和硕士分别毕业于北师大和北大计算机系。研究领域包括:互联网营销、大数据营销、社会网络分析,论文发表于《营销科学学报》、《管理科学》、《Journal of Business Ethics》、《Enterprise Information Systems》等,曾主持和参与多个国家自然科学基金项目,同时负责市策大赛、心理精英赛两个全国性比赛的运营与执行工作。

在人工智能时代,新兴技术在不同应用场景得到了广泛应用。市场调研作为消费者洞察与管理决策的核心工作,人工智能与调研的深入结合将使调研效率得到飞速提升。同时,利用人工智能技术也将对调研行业发展和人才培养起到重要的影响。该报告将介绍如何利用人工智能技术提升市场调研效率,并且调研行业人才培养如何能够进一步提升质量。

殷磊,主题:WealthGPT——让投资更简单

殷磊博士现任微众银行资深室经理,智能资管负责人,负责基于AI与另类数据驱动的资产管理和风险管理。殷磊博士带领团队获得2021年彭博量化大赛特等奖;同时,其带领研发的新一代ESG投资平台“揽月”荣获《哈佛商业评论》中国新增长创新实践榜单,2020年证券期货业金融科技研究发展中心(深圳)2020年度研究课题一等奖。殷磊博士之前曾任百度慧眼负责人,去哪网技术总监,简普科技风控技术负责人。

投资是一项具有挑战性的任务。然而,随着科技的飞速发展,我们有了更多机会利用最新的技术来改进投资决策过程。本次演讲将介绍一个为投资而生的大模型WealthGPT,以及其在宏观市场判断、板块轮动分析、个性化投资建议层面的应用。同时,演讲还会剖析WealthGPT如何帮助机构构建ESG评级体系,促进社会责任投资和绿色主题基金的发展。

张丹,主题:面向落地的数据分析:让“可能”变成了“可行”

微软MVP,R语言实践者,北京青萌数海科技有限公司CTO。10年以上互联网应用架构经验,在R、大数据、数据分析等方面有深厚的积累。精通量化投资交易策略,熟悉中国金融二级市场、交易规则和投研体系。 熟悉数据学科方法论,在海关、外汇等监管科技领域均有落地项目。

数据分析要解决实际业务场景问题,伪需求、不清晰的目标,都会造成项目失败。数据分析不只是指标体系、更不是指标堆积,市场在变,数据也在变,我们的知识结构也要跟着变化。数据分析是跨学科的工作,对人的要求也越来越高,调包侠的时代已过。要以新的视角,看数据、看业务、看技术发展、看我们自己,适应变化,才能把项目做好、落地。

以我多年的对数据分析的实际经验,借助R语言让“可能”变成“可行”。

高天辰,主题:基于神经网络的统计文献引用数预测

高天辰,厦门大学数理统计博士在读,研究兴趣包括:复杂网络数据的统计建模,大数据营销,进化博弈论与生物统计。在《Expert Systems with Applications》、《Journal of the Royal Statistical Society Series C Applied Statistics》,《Statistics and Its Interface》、《经济管理学刊》等期刊发表或被接受论文5篇,参加编著《网络结构数据分析与应用》等教材。

2.2 相关照片

会议在本届主席,中国人民大学统计学院2020级本科生王佳恒的欢迎辞中拉开序幕。王佳恒对本次 R 会作简要介绍,回顾过去的同时展望未来。

张志华(北京大学):现代人工智能的本质、途径和方向

肖诗汉(华为技术有限公司):昇思MindSpore技术创新进展和超大规模AI实践

主场,500人的礼堂,基本满了。

分会场,100人的教室,做了有一半以上。

晚上有主办方组织的大聚餐,由于人太多了,现场一直在找位置坐。

本次会议氛围非常热烈,在会议期间,参与者们展现出了高涨的热情和积极的互动。各个线下会场的参会者累计达到400人次;线上各平台统计观看超过二十万人次,其中主会场观看人次达到7.5万。

转载请注明出处:
http://blog.fens.me/meeting-r-agi-20231125