Go_形態素解析
date
Nov 24, 2022
slug
morphologicalAnalysis
status
Published
tags
Golang
summary
Golang形態素解析
type
Post
Golangでも簡単で日本語の形態素解析ができます。(環境構築はGoogle先生にお願いします。)
たまたまネット上の話題に対して、Pythonでポジティブがネガティブが分析しています。いきなりGoで試したい。やりました。
コードの概要
パッケージと定数
package main import ( "fmt" "log" "os" "strings" "github.com/go-gota/gota/dataframe" "github.com/go-gota/gota/series" "github.com/shogo82148/go-mecab " "golang.org/x/text/encoding/japanese" "golang.org/x/text/transform" )
上記のコードは、
main
パッケージを使用しています。また、以下のパッケージもインポートされています。fmt
:標準出力のためのパッケージ
log
:エラーログのためのパッケージ
os
:ファイル操作のためのパッケージ
strings
:文字列操作のためのパッケージ
github.com/go-gota/gota/dataframe
:データフレーム操作のためのパッケージ
github.com/go-gota/gota/series
:シリーズ操作のためのパッケージ
github.com/shogo82148/go-mecab
:形態素解析のためのパッケージ
golang.org/x/text/encoding/japanese
:日本語のエンコーディングのためのパッケージ
golang.org/x/text/transform
:テキストの変換のためのパッケージ
const BOSEOS = "BOS/EOS"
BOSEOS
は定数として定義されています。この定数は、形態素解析結果の特徴の先頭にある特別なタグを表しています。構造体
type NodeInfo struct { Surface string POS string POS1 string POS2 string BaseForm string PN float64 }
NodeInfo
構造体は、形態素解析結果のノード情報を格納するために使用されます。各フィールドは以下のような情報を保持します。Surface
:表層形(文字列)
POS
:品詞(文字列)
POS1
:品詞細分類1(文字列)
POS2
:品詞細分類2(文字列)
BaseForm
:基本形(文字列)
PN
:PN値(浮動小数点数)
type OutInfo struct { id string text string Pn float64 }
OutInfo
構造体は、解析結果を格納するために使用されます。各フィールドは以下のような情報を保持します。id
:ID(文字列)
text
:テキスト(文字列)
Pn
:PN値(浮動小数点数)
main
関数
func main() { tagger, _ := mecab.New(map[string]string{"output-format-type": "wakati"}) defer tagger.Destroy() text := "見えない" dicList, err := parseToNode(tagger, text) if err != nil { log.Fatal(err) } fmt.Println(dicList) dfc := dataframe.LoadStructs(dicList ) meand := dfc.Col("PN").Mean() oinfs := []OutInfo{} oinfs = append(oinfs, OutInfo{ id: "1", text: text, Pn: meand, }) for _, v := range oinfs { fmt.Printf("%s\t%f\n", v.text, v.Pn) } }
main
関数はプログラムのエントリーポイントです。以下の処理を行います。mecab.New
関数を使用して形態素解析器(tagger
)を作成します。また、defer
ステートメントを使用して関数終了時にtagger.Destroy()
を呼び出し、解放処理を行います。
- 解析対象のテキスト(
text
)を定義します。
parseToNode
関数を呼び出して形態素解析を行い、解析結果をdicList
に格納します。
- 解析結果を表示します。
dataframe.LoadStructs
関数を使用してデータフレーム(dfc
)を作成します。
- データフレームの
PN
列の平均値を計算し、meand
に代入します。
- 解析結果を
OutInfo
のスライス(oinfs
)に追加します。
oinfs
の要素をループして、テキストと PN 値を表示します。
形態素解析関数
func parseToNode(m mecab.MeCab, text string) ([]NodeInfo, error) { dicList := make([]NodeInfo, 0) node, err := m.ParseToNode(text) if err != nil { return nil, err } for ; !node.IsZero(); node = node.Next() { if !strings.HasPrefix(node.Feature(), BOSEOS) { fts := strings.Split(node.Feature(), ",") nodeInfo := NodeInfo{ Surface: node.Surface(), POS: fts[0], POS1: fts[1], POS2: fts[2], BaseForm: fts[6], PN: parsePN(node.Surface()), } dicList = append(dicList, nodeInfo) } } return dicList, nil }
parseToNode
関数は、形態素解析を行い、解析結果を NodeInfo
のスライスとして返します。引数として形態素解析器(m
)と解析対象のテキスト(text
)を受け取ります。- 空の
dicList
スライスを作成します。
m.ParseToNode
関数を使用してテキストを解析し、解析結果の最初のノードを取得します。
- ノードが存在する限り、以下の処理を繰り返します。 -
ノードの特徴を取得し、
BOSEOS
で始まっていないかを確認します。- ノードの特徴をカンマで分割し、各フィールドに割り当てます。
NodeInfo
構造体を作成し、解析結果の情報をフィールドに格納します。
dicList
にNodeInfo
を追加します。
- 解析結果の
dicList
を返します。
PN分析関数
func parsePN(v string) float64 { f, err := os.Open("pn_ja.csv") defer f.Close() if err != nil { log.Fatal(err) } r := transform.NewReader(f, japanese.ShiftJIS.NewDecoder()) df := dataframe.ReadCSV(r) dfl := df.Filter( dataframe.F{Colname: "A", Comparator: series.Eq, Comparando: v}, ) if dfl.Nrow() == 0 { return 0 } if i, ok := dfl.Col("D").Val(0).(float64); ok { return i } return 0 }
parsePN
関数は、PN値を分析するために使用されます。引数として解析対象の文字列(v
)を受け取り、その文字列に対応するPN値を返します。"pn_ja.csv"
ファイルを開きます。処理が終了したらdefer
ステートメントでファイルを閉じます。
- 日本語のシフトJISエンコーディングを使用して、ファイルをテキストとして読み込むための
transform.NewReader
を作成します。
dataframe.ReadCSV
関数を使用して、CSVファイルをデータフレーム(df
)として読み込みます。
- データフレームのフィルタリングを行い、列
"A"
の値が解析対象の文字列と等しい行のみを取得します。
- 取得したデータフレーム(
dfl
)の行数が0であれば、PN値は0として返します。
dfl.Col("D").Val(0)
を使用して、列"D"
の最初の値を取得します。
- 値が浮動小数点数であれば、その値をPN値として返します。そうでなければ、0を返します。
以上、です!