京橋のバイオインフォマティシャンの日常

まずは、データ分析、コマンドラインのメモとして

Rの「reticulate」を使えば、Pythonライブラリがインポート・実行できる。そして、R上で「googletrans」を用いた日英翻訳をやってみた件

Rの reticulateパッケージは、Python と R の連携性を高めるツール群である*1

つまりは、Rセッション内でPythonスクリプトやライブラリをインポートして、シームレスにPythonコードを実行できるなど、RからPythonを呼び出すことができる。

また、RとPythonのオブジェクト間の変換も可能である(Ex. R データフレーム <=> Pandas)。

reticulate::importを使用して、R上で、googletransライブラリを読み込んで、日=>英翻訳、戻し翻訳をやってみる。

今回の内容

googletransライブラリのメリット・デメリット

Googletransは、Google翻訳APIを実装した、無料のPythonライブラリである。

メリット

  • 翻訳速度が早い - translate.google.comと同じサーバー使用

  • 自動言語検出

  • バルク翻訳

  • カスタマイズ可能なサービスURL

  • HTTP/2 サポート

デメリット

  • 1日に使用できる回数制限

  • テキストは最大15kまで

  • 安定性がいまいち

  • Googleで正式に提供するAPI Google Cloud Translation は有料

googletransのインストール

まずは、ターミナルを立ち上げて、 pipで、googletransをインストールする。

$ pip install googletrans

Pythonとpipの設定はこちらの記事を参照のこと。

skume.hatenablog.com

reticulateのセットアップ

Rを起動して、reticulateをインストールして、ロードする。

install.packages("reticulate")
library(reticulate)

Pythonパスを選択して、reticulate::py_config()で確認する。

reticulate::use_python("/usr/local/bin/python", required =T)

reticulate::py_config()

#python:         /usr/local/bin/python
#libpython:      /usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/config-3.7m-darwin/libpython3.7.dylib
#pythonhome:     /usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7:/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7
#version:        3.7.7 (default, Mar 10 2020, 15:43:33)  [Clang 11.0.0 (clang-1100.0.33.17)]
#numpy:          /Users/skume/Library/Python/3.7/lib/python/site-packages/numpy
#numpy_version:  1.16.3
#
#NOTE: Python version was forced by use_python function

/usr/local/bin/pythonとなっており、これでOK。

RからPython googletransを呼び出す

Pythonライブラリのインポートには、 reticulate::import関数を使う。

gt <- reticulate::import(module = "googletrans")

# GtにTranslator関数を渡す
Gt <- gt$Translator()

ヘルプ表示については、補足を参照のこと。

googletransの実行

挨拶の基本として、こんにちわを英訳してみる。

Result <- Gt$translate(text="こんにちわ", src="ja", dest='en')

class(Result)
#[1] "googletrans.models.Translated"
#[2] "python.builtin.object"        

Result
#Translated(src=ja, dest=en, text=Hello, pronunciation=None, extra_data="{'translat...")
#"text="の後ろが、翻訳された結果

translateのオプション

text: 翻訳する文字列

src: 元文の言語(指定無しなら、自動判定)

ja: 日本語, en: 英語, de: ドイツ語, ko: 韓国語, fr: フランス語

dest: 翻訳したい言語(指定無しなら、英語)

結果が"googletrans.models.Translated"で返ってくるので、"text="後の翻訳された結果を抜き出すスクリプトが必要となる。

ここでは、CutTextという関数を新たに定義してみる。

"CutText" <- function(x){
  strsplit(strsplit(as.character(x), ", text=")[[1]][2], ", pronunciation=")[[1]][1]
  }

a <- CutText(Result)
a

#[1] "Hello"

もう少し長い文章で、実行してみる。

例文

Googleの無料サービスなら、単語、フレーズ、ウェブページを英語から100以上の他言語にすぐに翻訳できます。

ResultX <- Gt$translate(text="Googleの無料サービスなら、単語、フレーズ、ウェブページを英語から100以上の他言語にすぐに翻訳できます。", 
                        src="ja", dest='en')

b <- CutText(ResultX)
b

#[1] "With Google's free service, you can instantly translate words, 
#phrases and web pages from English into over 100 other languages."

#さらに、戻し翻訳をしてみると

ResultY <- Gt$translate(text=b, src="en", dest='ja')
c <- CutText(ResultY)
c

#[1] "Googleの無料サービスを利用すると、単語、フレーズ、ウェブページを
#英語から他の100以上の言語に即座に翻訳できます。"

結果、ほぼ違和感なく、戻し翻訳もできている。

まとめ

R上で、日英翻訳ができれば、いちいちGoogle翻訳のページにいかなくても良くなるので、少しだけ便利かも。

最終的には、上記全てを組み込み関数にしたいところ、、

補足

Rから、Python ライブラリのヘルプ表示

#py_help(gt)
#OR
#py_help(gt$client$Translator)
#OR
#py_help(gt$Translator)
#OR
py_help(gt$Translator$translate)

以下が、ヘルプの表示結果

Help on class Translator in module googletrans.client:

class Translator(builtins.object)
 |  Translator(service_urls=None, user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64)', raise_exception=False, proxies: Dict[str, httpcore._sync.base.SyncHTTPTransport] = None, timeout: httpx._config.Timeout = None)
 |  
 |  Google Translate ajax API implementation class
 |  
 |      You have to create an instance of Translator to use this API
 |  
 |      :param service_urls: google translate url list. URLs will be used randomly.
 |                           For example ``['translate.google.com', 'translate.google.co.kr']``
 |      :type service_urls: a sequence of strings
 |  
 |      :param user_agent: the User-Agent header to send when making requests.
 |      :type user_agent: :class:`str`
 |  
 |      :param proxies: proxies configuration.
 |                      Dictionary mapping protocol or protocol and host to the URL of the proxy
 |                      For example ``{'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}``
 |      :type proxies: dictionary
 |  
 |      :param timeout: Definition of timeout for httpx library.
 |                      Will be used for every request.
 |      :type timeout: number or a double of numbers
 |  ||||||| constructed merge base
 |      :param proxies: proxies configuration.
 |                      Dictionary mapping protocol or protocol and host to the URL of the proxy
 |                      For example ``{'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}``
 |      :param raise_exception: if `True` then raise exception if smth will go wrong
 |      :type raise_exception: boolean
 |  
 |  Methods defined here:
 |  
 |  __init__(self, service_urls=None, user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64)', raise_exception=False, proxies: Dict[str, httpcore._sync.base.SyncHTTPTransport] = None, timeout: httpx._config.Timeout = None)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  detect(self, text, **kwargs)
 |      Detect language of the input text
 |      
 |      :param text: The source text(s) whose language you want to identify.
 |                   Batch detection is supported via sequence input.
 |      :type text: UTF-8 :class:`str`; :class:`unicode`; string sequence (list, tuple, iterator, generator)
 |      
 |      :rtype: Detected
 |      :rtype: :class:`list` (when a list is passed)
 |      
 |      Basic usage:
 |          >>> from googletrans import Translator
 |          >>> translator = Translator()
 |          >>> translator.detect('이 문장은 한글로 쓰여졌습니다.')
 |          <Detected lang=ko confidence=0.27041003>
 |          >>> translator.detect('この文章は日本語で書かれました。')
 |          <Detected lang=ja confidence=0.64889508>
 |          >>> translator.detect('This sentence is written in English.')
 |          <Detected lang=en confidence=0.22348526>
 |          >>> translator.detect('Tiu frazo estas skribita en Esperanto.')
 |          <Detected lang=eo confidence=0.10538048>
 |      
 |      Advanced usage:
 |          >>> langs = translator.detect(['한국어', '日本語', 'English', 'le français'])
 |          >>> for lang in langs:
 |          ...    print(lang.lang, lang.confidence)
 |          ko 1
 |          ja 0.92929292
 |          en 0.96954316
 |          fr 0.043500196
 |  
 |  translate(self, text, dest='en', src='auto', **kwargs)
 |      Translate text from source language to destination language
 |      
 |      :param text: The source text(s) to be translated. Batch translation is supported via sequence input.
 |      :type text: UTF-8 :class:`str`; :class:`unicode`; string sequence (list, tuple, iterator, generator)
 |      
 |      :param dest: The language to translate the source text into.
 |                   The value should be one of the language codes listed in :const:`googletrans.LANGUAGES`
 |                   or one of the language names listed in :const:`googletrans.LANGCODES`.
 |      :param dest: :class:`str`; :class:`unicode`
 |      
 |      :param src: The language of the source text.
 |                  The value should be one of the language codes listed in :const:`googletrans.LANGUAGES`
 |                  or one of the language names listed in :const:`googletrans.LANGCODES`.
 |                  If a language is not specified,
 |                  the system will attempt to identify the source language automatically.
 |      :param src: :class:`str`; :class:`unicode`
 |      
 |      :rtype: Translated
 |      :rtype: :class:`list` (when a list is passed)
 |      
 |      Basic usage:
 |          >>> from googletrans import Translator
 |          >>> translator = Translator()
 |          >>> translator.translate('안녕하세요.')
 |          <Translated src=ko dest=en text=Good evening. pronunciation=Good evening.>
 |          >>> translator.translate('안녕하세요.', dest='ja')
 |          <Translated src=ko dest=ja text=こんにちは。 pronunciation=Kon'nichiwa.>
 |          >>> translator.translate('veritas lux mea', src='la')
 |          <Translated src=la dest=en text=The truth is my light pronunciation=The truth is my light>
 |      
 |      Advanced usage:
 |          >>> translations = translator.translate(['The quick brown fox', 'jumps over', 'the lazy dog'], dest='ko')
 |          >>> for translation in translations:
 |          ...    print(translation.origin, ' -> ', translation.text)
 |          The quick brown fox  ->  빠른 갈색 여우
 |          jumps over  ->  이상 점프
 |          the lazy dog  ->  게으른 개
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)

googleLanguageRの「No authorization yet in this session!」問題を解決するのは面倒そう!【6/27追加】

Google Cloud Translation API

googleLanguageRというGoogle翻訳APIがあるのだが、そのまま実行すると、エラーとなる。

install.packages("googleLanguageR")
library(googleLanguageR)

text <- "to administer medicince to animals is frequently a very difficult matter, and yet sometimes it's necessary to do so"

# 英語 => 日本語 への翻訳
gl_translate(text, target = "ja")$translatedText

#2020-06-27 19:44:48 -- Translating text: 115 characters - 
#  ℹ 2020-06-27 19:44:48 > No authorization yet in this session!
#  ℹ 2020-06-27 19:44:48 > No  .httr-oauth  file exists in current working directory.  Do library authentication steps to provide credentials.
#エラー: Invalid token

https://cran.r-project.org/web/packages/googleAuthR/vignettes/google-authentication-types.html Google authentication types for R

github.com

このあたりで、解決策について、いろいろと議論されているが、設定不要のgoogletransを使うので良いのではないかと思う。

参考資料

pypi.org

rstudio.github.io