行列屋さんの作業ログ

行列まわりで色々やってたエンジニアの作業メモ&国内外旅行記ブログ

板門店に行ってみた 韓国5泊6日 旅行記⑥ 板門店ツアー後編

この記事は下の記事の続きです
liberaldays.hatenablog.com


韓国旅行4日目,板門店ツアーの後半記事になります.臨津閣国民観光地と昼食.前半は上のリンクから.
参加したツアーはコレ
【ソウル発・南北境界線ツアー】板門店(JSA)ツアー☆土曜日にJSAに行けるのは、このツアーだけ!<火・土/午前/日本語ガイド/昼食付> | ソウルの観光・オプショナルツアー専門 VELTRA(ベルトラ)

続きを読む

板門店に行ってみた 韓国5泊6日 旅行記④ 高速バスで釜山からソウルへ

この記事は下の記事の続きです
liberaldays.hatenablog.com


韓国旅行3日目.今日は午前中に朝鮮通信使歴史館を訪問し,午後に高速バスにのってソウルへと移動します.本来なら4時間半で着くはずが渋滞に巻き込まれ6時間かかりました.

続きを読む

板門店に行ってみた 韓国5泊6日 旅行記③ 韓国入国と釜山観光,そして蟹

この記事は下の記事の続きです
liberaldays.hatenablog.com



韓国旅行記事2日目です.
今日の目標は明日のソウル行高速バスを予約することと,明日まで時間を潰すこと.の2点.スマホ買いたてで盗難を恐れ写真を撮れていないのですがご了承下さい.

続きを読む

板門店に行ってみた 韓国5泊6日 旅行記② パンスタークルーズ乗船

この記事は下の記事の続きです
liberaldays.hatenablog.com


韓国旅行1日目,今日の目標は船に無事乗船することです.
パンスタークルーズの船は大阪南港を15時に出港します.船の予約確認書には14時までにフェリーターミナルに来るよう指示がありました.

東京駅を10:40発の新幹線のぞみに乗車し,新大阪に13:13,フェリーターミナルの最寄り駅コスモスクエア駅に13:57に到着するルートで向かいます.(若干遅れぎみですが前の予定があったので...)
ちなみに東京-大阪間の新幹線代(往復:学割乗車券14000円+特急券9740円)がこの旅行で一番大きな支出です.

続きを読む

板門店に行ってみた 韓国5泊6日 旅行記① 計画編

また旅行記に戻ります.
2016年の9月,5泊6日の旅程で韓国に行きました.今回の旅行の最大の目的は北朝鮮との境界線上に位置する板門店の訪問.
また、日本からの移動手段には大阪-釜山のフェリー(パンスタークルーズ)を選択。5泊のうち2泊は船上でした.
人生初の韓国(そして北朝鮮)旅行は楽しいものとなりました.その様子をお伝えします.
スマホの事情で写真が少ないのですが,大目にみて頂ければ...

旅程

9/14 出国(@東京,大阪)
9/15 韓国入国・釜山観光(@釜山)
9/16 ソウルへ移動(@釜山,ソウル)
9/17 板門店DMZ観光(@ソウル,板門店)
9/18 釜山へ移動,出国(@ソウル,釜山)
9/19 日本入国(@大阪,東京)

旅行の契機

韓国旅行の契機は,友人から送られてきた送られてきた一通のLINE「くまぽんで韓国行きフェリーが安く手に入る」というものでした.
そのくまぽんのページがこちら(現在は販売終了).
kumapon.jp


大阪南港に停泊するフェリー

フェリーはサンスターラインという会社が提供しているもので,大阪-釜山を18時間30分で結んでいます.船の名前はパンスタードリーム.この船のデラックススイートが通常往復5万円のところ15800円となります.(食事はコース料理からビュッフェにグレードダウンしますが)
この安さと海外に船で行く経験ができることに惹かれ,旅行を決意しました.
www.panstar.jp

フェリーの運行日と相談し,水曜日(9/14)に大阪を出港する便で日本を立ち,日曜日(9/18)に釜山を出港する便で帰国することとしました.つまり韓国では3泊4日.ところでこの時期は韓国の旧盆「秋夕(チュソク)」.韓国ではこの時期は家族一緒に過ごすらしく商業施設も休み.いわゆる普通の観光が出来なくなる可能性がありました(実際は杞憂でしたが).
japanese.visitkorea.or.kr

そこで休日など関係のない状態が残念ながら続いている板門店DMZを観光するツアーに参加することにしました.
後はホテルの手配,釜山-ソウル間の交通手段の手配,海外WiFiの手配を済ませて旅行初日を待ちます.

わかりやすさのため,旅行記は次の記事から始めます.

次の記事はこちら
liberaldays.hatenablog.com


日々の生活にhappyをプラスする|ハピタス

一行ごとのJSONをRで読み書きする.

久しぶりに旅行記以外のものを執筆します.

データ入出力の形式として現在はJSONがとにかく広く使われている気がします.私のプロジェクトでもJSONを頻繁に使うのですが,1行毎にJSONのオブジェクトが格納され末尾にカンマがないという,ちょっと特殊なJSON(一行JSONと勝手に呼んでます)をRで読み書きする機会があったのでそのやり方をまとめておきます.

同様のことをpythonでやっている人は発見しました.
qiita.com
また,jq コマンドというjson操作に特化したコマンドを使用して処理する方法もありました.
qiita.com
ただjqコマンドを入れられない環境もあったので,使わない方法でアプローチします.


よくあるJSONはこんな感じ.

[
{
        "foo" : 10,
        "bar" : 20,
        "arr" :["a","b"]
},
{
        "foo" : 30,
        "bar" : 40,
        "arr" :["c","d"]
}
]

Rではjsonliteパッケージで読み込めます.

df <- jsonlite::fromJSON(txt='./sample.json')
print(df)
| foo| bar|arr  |
|  10|  20|a, b |
|  30|  40|c, d |

一方で今回読み書きしたいJSON(一行JSON)は次のような形式です.

{"foo" : 10,"bar" : 20,"arr" :["a","b"]}
{"foo" : 30,"bar" : 40,"arr" :["c","d"]}

この形式をアプリケーションのログファイル等で使用すると便利なのですが,(少なくともjsonliteでは)想定されていない形式のためそのまま読み書きすることは出来ません.
具体的には,

  • ファイルの先頭,末尾に[]がない
  • 各行末尾に「,」がない

という違いがあります.
そこでシェルスクリプトを噛ませてjsonliteで対応可能な形式に変換を行います.

読み込む

{"foo" : 10,"bar" : 20,"arr" :["a","b"]}
{"foo" : 30,"bar" : 40,"arr" :["c","d"]}

上のようなデータを次のシェルスクリプトで変形します.

#!/bin/bash
#convertJSON.sh
LF=$(printf '\\\012_')
LF=${LF%_}
sed '/^$/d' $1 | sed -e 's/}{/}'"$LF"'{/g' | sed "s/$/,/g" | sed "1s/^/[/" | sed '$s/},/}]/'

$1が読み込みたいデータのファイルパスで,sed '/^$/d'で空行を削除,sed -e 's/}{/}'"$LF"'{/g'で一行に複数データが書き込まれていた際データ毎に改行させます.
sed "s/$/,/g" | sed "1s/^/[/" | sed '$s/},/}]/'でファイル先頭,末尾への[]の挿入と,各行末尾への「,」の挿入を行っています.
(/bin/shでなく/bin/bashを呼び出してるのは改行が上手くいかなかったから...のはずですが再検証したらshでも動いた.)

JSON入力の全操作をRで完結させるため,上のスクリプト(convertJSON.shとします)を使い関数readMyJSONを作成しました.

readMyJSON <- function(jsonFile){
	jsonTmp <- tempfile()
	system(paste0('./convertJSON.sh ',jsonFile,'> ',jsonTmp))
	df <- fromJSON(jsonTmp)
	try({file.remove(jsonTmp)})
	return(df)
}

この関数を使うと一行JSONのファイルを普通のJSONに変換,jsonliteで読み込みデータフレームとして返してくれます.

書き込む

データフレームを一行JSON形式で書き込むためには,jsonliteで一度普通のJSONで書き込んだ後,シェルスクリプトで整形します.
以下が使用した関数writeMyJSONとシェルスクリプトwriteJSON.shです.

writeMyJSON <- function(df,filename){ 
	jsonData <- toJSON(df)
	jsonTmp <- tempfile()
	write(jsonData,file=jsonTmp)
	system(paste0('./writeJSON.sh ',jsonTmp,' > ',filename))
	try({file.remove(jsonTmp)})
	return(TRUE)
}
#!/bin/bash
#writeJSON.sh
LF=$(printf '\\\012_')
LF=${LF%_}
sed -e 's/},{/}'"$LF"'{/g' $1 | sed "1s/\[//" | sed '$s/}]/}/' 

これで一行JSONの書き込みも出来ました.

ただtempfileに一時的にファイルを書き込んでいるため,巨大なファイルを扱うときのパフォーマンスはよくありません.私が扱うのは大きくとも数100MB程度のJSONファイルなのでなんとかなってはいますが.(でもそれ以上に大きなデータはJSONでは扱わないきもする.)