たつをの ChangeLog

19 件 見つかりました。

1 2 3 4 [ 次へ ]

CSV ファイルで、テキストのカラムにカンマが入っているんだけど、そのカラムがダブルクォート文字で囲まれていないときの対処法について。

ときどきそういうデータがあるのです。
適当なその場しのぎスクリプトで CSV 出力した結果とか。
で、それをなんとかして使わないといけない場面もあるのです。
怒ってないです。

例えば、全部で10カラムのCSV。
第4カラムにテキスト。

0,2,0,こんにちは,50,0,0,0,0,0
1,1,1,さようなら,0,0,0,0,0,0

CSV だからカンマ区切りなんだけど、テキストにカンマが含まれてる場合あり。
しかもダブルクォートで囲まれていない。
区切りのカンマと区別つかなくて困る。

理想:
1,1,0,"ああ,いい,ううう。",21,0,0,0,0,0
0,2,0,"あれれれ,",50,0,0,0,0,0

現実:
1,1,0,ああ,いい,ううう。,21,0,0,0,0,0
0,2,0,あれれれ,,50,0,0,0,0,0

こういうときは、前から3カラム(=4-1)、後ろから6カラム(=10-4)を除いた残りすべてを一つのテキストとする作戦で。

1,1,0,ああ,いい,ううう。,21,0,0,0,0,0

↓ カンマで分割してリストにする

1 1 0 ああ いい ううう。 21 0 0 0 0 0

↓ 前と後ろのカラムを取る

[1 1 0] ああ いい ううう。 [21 0 0 0 0 0]

↓

ああ いい ううう。

↓ 残りをカンマで繋ぎ直し、ダブルクォートで囲む

"ああ,いい,ううう。"

↓ さっき取った、前と後ろのカラムと合わせて最終的な CSV にする

1,1,0,"ああ,いい,ううう。",21,0,0,0,0,0

Perl


Perl で書くとこんな感じ。
my $IX = 4; # 4番目のカラムがカンマ入りテキスト
my $N = 10; # 全部で10カラム
while (<>) {
    chomp; # 末尾の改行削除
    my @F = split(",", $_, -1); # 読み込んだ CSV 行をカンマで切ってリストへ
    my @pre = @F[0..($IX-2)]; # 前から IX-1 個分のカラム
    my @post = @F[$#F-($N-$IX-1)..$#F]; # 後ろから N-IX 個分のカラム
    my $text = join(",", @F[($IX-1)..($#F-($N-$IX))]); # カンマ入りテキスト
    print join(",", @pre, "\"$text\"", @post)."\n"; # CSV に戻す
}

splice 関数を使ったバージョン。
my $IX = 4; # 4番目のカラムがカンマ入りテキスト
my $N = 4; # 全部で10カラム
while (<>) {
    chomp; # 末尾の改行削除
    my @F = split(",", $_, -1); # 読み込んだ CSV 行をカンマで切ってリストへ
    my @ts = join(",", splice(@F, $IX-1, (@F-$N) + 1)); # テキスト部分の抜き出し
    splice(@F, $IX-1, 0, qq(").join(",", @ts).qq(")); # ""をつけて戻す
    print join(",", @F)."\n"; # CSV に戻す
}

Perl の split 関数の第3引数の "-1" についてはこちらを参照。

Python


Python で書くとこんな感じ。
右側から分割してくれる rsplit 関数がこの用途に便利。
ID = 4
N = 10
with open('sample.csv') as f:
    for line in f.read().splitlines():
        pre = line.split(",", ID - 1)
        post = pre[-1].rsplit(",", N - ID)
        l = pre[:-1]
        l.append('"' + post[0] + '"')
        l.extend(post[1:])
        print(",".join(l))

1,1,0,ああ,いい,ううう。,21,0,0,0,0,0

↓ 最初の split で前から4分割(3箇所で切断)

1 / 1 / 0 / ああ,いい,ううう。,21,0,0,0,0,0

↓ 一番右の塊を次の rsplit で後ろから7分割(6箇所で切断)。

ああ,いい,ううう。 / 21 / 0 / 0 / 0 / 0 / 0

↓

1 / 1 / 0 / ああ,いい,ううう。 / 21 / 0 / 0 / 0 / 0 / 0

↓

1,1,0,"ああ,いい,ううう。",21,0,0,0,0,0

おわりに


カンマ入りテキストカラムが複数ある場合はちょっと難しい。めんどくさいのであきらめましょう。桁区切りカンマ入りの数値がクォート無しで複数カラムあるとかも。

あと、上のスクリプトではテキストにダブルクォートが含まれててエスケープされてない場合は考慮してません。join で "\t" を使って TSV にしとくのが良いかと。テキストに "\t" がない前提で。

今更ながら、MongoDB を macOS と CentOS7 で試してみた。ざっくりとだけど一通り流れは理解できた。


目的の一つは、ある商品群の価格変化を記録していくこと。Keepa みたいなイメージ。私がよくやっている「TSVファイルに追加していく単純な方式」と比べ、速度や使い勝手がどうなのかは、サーバで運用しながら調べていく予定。

macOS へのインストール

環境: MacBook Pro (13-inch, 2017), macOS 10.15.7。

これらを参考に。

brew install mongodb
今はできない。代わりの方法。
brew tap mongodb/brew
brew install mongodb-community

cat /usr/local/etc/mongod.conf
systemLog:
  destination: file
  path: /usr/local/var/log/mongodb/mongo.log
  logAppend: true
storage:
  dbPath: /usr/local/var/mongodb
net:
  bindIp: 127.0.0.1

起動:
brew services start mongodb-community

CentOS7 へのインストール

環境: さくらVPS, CentOS 7。
MongoDB の current version は 4.4。

ここの手順に従う。

まず、"/etc/yum.repos.d/mongodb-org-4.4.repo" を作り、それから yum を実行。
sudo yum install -y mongodb-org

起動:
sudo systemctl start mongod

動作の確認

mongo
use test
show dbs
db.stats()
# db.createCollection('hello')
show collections
db.hello.stats()
db.hello.insert({'uid':123, 'test':'World'})
db.hello.insert({'uid':"oreore", 'text':'This is a pen.'})
db.hello.insert({'uid':"you", 'text':'Today is ...'})
db.hello.find()
db.hello.findOne()
db.hello.findOne()["uid"]
var r = db.hello.find()
while (r.hasNext()) printjson(r.next())
quit()

バックアップ&リストア

mongodump -d test
mongo
use test
db.hello.drop()
db.dropDatabase()
show dbs
quit()
mongorestore ./dump

監視

mongotop
mongostat

取り出し

db.hello.find({}, {uid: 1, text: 1, _id: 0})
db.hello.find({$or: [{'uid':123}, {'uid':"you"}]}, {uid: 1, text: 1, _id: 0})
db.hello.find({$or: [{'uid':123}, {'uid':"you"}, {'uid':"oreore"}]}, {ud: 1, text: 1, _id: 0})
db.hello.find({$or: [{'uid':123}, {'uid':"you"}, {'uid':"NO"}]}, {uid: 1, text: 1, _id: 0})

更新

db.hello.update({"uid" : "you"}, {$set : {"text":"こんにちは"}})
db.hello.insert({'uid':"me", 'hist':[{'ymd':20201020,'val':12}]})
db.hello.update({'uid':"me"}, {$push:{'hist':{'ymd':20201024,'val':38}}})
db.hello.update({'uid':"me"}, {$set:{'last-update':ISODate("2020-10-24T12:55:15")}})

Python

インストール:
pip install pymongo
テストスクリプト:
from pymongo import MongoClient
import datetime

dt_now = datetime.datetime.now()

client = MongoClient('localhost',27017)
db = client.test
col = db.hello

for i in col.find():
    print(i)

col.update_one({'uid':"me"}, {
    '$push':{'hist':{'ymd':dt_now,'val':189}},
    '$set':{'last-update':dt_now}
})

print(col.find_one({'uid':"me"}))

参考


5月頭に書いた記事「東京都の新型コロナウイルスでの年代別死亡者数が公表されたのでグラフを作ってみた[2020-05-02-1]」の続きです。
6月までの年代別死亡者数が出ていたのでグラフをアップデートしました。
python, jupyter notebook, pandas, matplotlib を使っています。

  • 6月までの死亡者 都が詳細公表|NHK 首都圏のニュース
    亡くなった人のうち、20代は1人で全体に占める割合は0.3%、30代は1人で0.3%、40代は5人で1.5%、50代は16人で4.9%、60代は32人で9.9%、70代は93人で28.6%、80代は113人で34.8%、90代は61人で18.8%、100歳以上は3人で0.9%でした。

10万人あたり陽性患者数と死亡者数を年代別に表示したもの。

TokyoCovid19Death 東京都 新型コロナウイルス死亡者 (2020-06-30)

比較のために前回のグラフもあげておきます。

TokyoCovid19Death100K 東京都 新型コロナウイルス死亡者 (2020-05-01)

陽性患者はご存知の通り、若い世代に増えています。
一方、死亡者は高齢者に多いのですが、前回と比べると、高齢者の死亡率がかなり上がっています。

こちらは個別にいろいろ表示してみたもの。

TokyoCovid19Death 東京都 新型コロナウイルス死亡者 (2020-06-30)

左下の死亡者数÷陽性患者数(≒死亡率)。
件数は少ないのですが100歳以上は50%です。
80・90代は30%近くまで上昇。
前回は10%代でした。

高齢者には致命的なものだということが納得できます。

コード


ソースコードは前回のもの(Jupyter Notebook の HTML)とほぼ同じです。

年代別死亡者数の部分はもちろん更新しています。

  • 前回(2020-05-01)
    ddf['死亡者数'] = (0,0,0,0,1,9,18,40,38,16,0)
    
  • 今回(2020-06-30)
    ddf['死亡者数'] = (0,0,1,1,5,16,32,93,113,61,3)
    

過去記事


東京都の新型コロナの感染者数について

月曜は数が少ない

という意見をネットよくで見かけます。
(例:「東京 コロナ 月曜 少ない」のYahoo!検索(リアルタイム))

実際はどうなのか、東京都のデータで調べてみました。

各曜日の報告数の平均を月ごと出し、それの合計を分母に、その月の曜日別の報告数の割合を算出して、グラフにしました。

TokyoCovid19ReportDow

どうやら「月曜は数が少ない」というのは4月までの話のようです。最近は平準化されているように見えます。

週末に向けて報告数が増える傾向はありそうですが、なぜか水曜日は少なめですね。月曜よりも水曜が少ない。謎です。

前々から検査実施は土日が少なく、その影響で初めのうちは月曜の報告数が少なかったと思われます。しかし、土日の検査が少ない状況が変わらないのに、最近になって月曜の報告者数が増えている。謎です。

なお、7月はまだ2週間分しかない上、9日(木)からの200人越えの倍ブレイクという偏りがあるため、今回は6月末までのデータのみを使用しています。8月になったら7月のデータも加味します。

今回の作業のコードを、Jupyter Notebook の HTML ファイルとして置いておきます。ご自由にお使いください。検証もお願いします。

追記200802:

8月になったので7月分の集計を行いました。
その結果、7月はかなり明確に月曜が少ないことがくっきりと出ました。
土日の検査数の影響がきれいに出ています。
ということで、現在は「月曜だから数が少ない」と言えそうです。

TokyoCovid19ReportDow 20200731

東京都の集計の実態についての情報がありました。

  • 東京都の新規感染者数、昼には速報が どうやって集計? [新型コロナウイルス]:朝日新聞デジタル
    都によると、都が発表している1日あたりの感染者数は、前日午前9時の締め切り以降、当日午前9時までに都にファクスで報告された人数だ。
    都内での感染者数が最初のピークを迎えた4月は締め切りは正午ごろだった。だが、都が指標の公表を始めた5月半ばに午前9時に前倒ししたという。
    こうしたやりとりを重ねた末、年代別の人数や感染経路などと合わせて、午後7時~8時ごろ、その日の感染者の内訳が公表される。昼や午後に全体の感染者数のみがテレビやネットの速報で流れるのは、朝日新聞を含めて先に固まった感染者数を取材している報道機関があるためだ。
    ただ、都の担当者は、実際に検査で陽性と判明した日から都の公表までに「3日ほどかかる」と認める。その理由はアナログな集計方法にある。感染がわかると、まず医師が患者の情報を記した発生届を作成する。それを各医療機関が管轄の保健所にファクスで送信する。受け取った保健所は、記載に不備がないか確認した上で、誤送信の可能性に備えて、個人情報を黒塗りにするなどして都にファクスで転送する。医師、保健所、都でそれぞれ作業が生じ、これまでの都の経験則から、検査結果の判明日から都が公表するまでにおおむね3日かかる傾向にあるという。

データサイエンティストに俺はなる!!
Python 初学者のタツヲです。

いまどきは高校の授業(情報II)でデータサイエンスをやるのですね。
文部科学省から教員用の資料が公開されてるのを知りました。
「情報II」を取った高校生がどんなことを学んでいるのかを知るために、さっそく調査です!


第3章がデータサイエンスの話題ですので、そこを読みました。

高等学校情報科「情報Ⅱ」教員研修用教材 第3章「情報とデータサイエンス」

で、読んでみた感想ですが、内容が本格的すぎて震える。
大学のデータサイエンス演習のテキストじゃないのかよ、これ。
流し読みでは一部ついていけないところも(真面目に読む必要あり)。
高校生のうちからこの辺をマスターできれば将来安泰でしょう、って即戦力すぎる。

第3章の目次です。
第3章「情報とデータサイエンス」
  • 学習11 データと関係データベース
  • 学習12 大量のデータの収集と整理・整形
  • 学習13 重回帰分析とモデルの決定
  • 学習14 主成分分析による次元削減
  • 学習15 分類による予測
  • 学習16 クラスタリングによる分類
  • 学習17 ニューラルネットワークとその仕組み
  • 学習18 テキストマイニングと画像認識

第3章のPDFは2つに分かれています。

第3章の冒頭。
本章の演習においては,表計算ソフトウェア,統計処理ソフトウェアR,プログラミング言語Pythonを想定している。Rに関しては,v.3.6以上,統合開発環境であるRStudioの利用が望ましい。Pythonに関しては,v.3.7以上で,AnacondaのJupyter Notebook,Jupyter Labo,Spyderなどの統合開発環境での利用を想定している。また一部の学習では,Google Colaboratoryも活用している。
こういう環境が整ってるって、ありがたい時代ですよねえ。

以下、各項目からキーワードをメモしていきます。
キーワードを眺めるだけで、だいたいの内容がわかるかと思います。

  • 学習11 データと関係データベース
    • 関係データベース(RDB), SQL, NoSQL
    • ヒストグラム, 階級, 母集団と調査, 信頼水準
    • 生存バイアス, 選択バイアス
    • pandas, read_csv, drop, drop_duplicates
    • CSV, JSON
    • Linked Open Data (LOD)
  • 学習12 大量のデータの収集と整理・整形
    • Data: USGS (U.S. Geological Survey), e-Stat
    • クローリング, Webスクレイピング
      • Python: request, Beautiful Soup4
      • R: rvest
    • データ操作: df.sort_values, ascending, sum
    • ワイドフォーマット(横持ち形式), ロングフォーマット(縦持ち形式), ピボットテーブル
    • データ操作: df.melt, pivot_table
    • 欠損値と異常値, NaN, NA, df.isnull, dropna, fillna
  • 学習13 重回帰分析とモデルの決定
    • 論理図: 特性要因図(フィッシュボーンダイアグラム), 要因連関図,イシューツリー,ロジックツリー,ロジックモデル
    • 構造化データ(行列データ)
    • 目的変数, 説明変数(予測子,要因変数)
    • 回帰モデル, 予測(推測), 要因分析
    • 重回帰モデル, 単回帰モデル, 最小二乗法
    • 適合度, 重相関係数R, 寄与率(決定係数)R^2, 自由度, 標準誤差
    • 重回帰分析の実行
      • Excel=>「データ」=>「データの分析」(アドインで設定)
      • Rもあり
    • モデル選択(モデリング), 変数選択, 過剰適合,過学習
    • モデル選択の基準: 自由度調整済み寄与率R^2, AIC(赤池の情報量規準)
    • 回帰係数の有意差の検定
    • 自動変数選択: 総当法, 変数増加法, 変数減少法, 変数増減法(ステップワイズ法)
    • ダミー変数, ロジスティック回帰分析
  • 学習14 主成分分析による次元削減
    • 次元削減(次元縮約), 主成分得点
      • Excel で第1,第2主成分: 最適化機能, ソルバー
    • 相関行列, 共分散行列
      • R: prcomp
    • 次元削減の基準: 累積寄与率, カイザー基準, スクリープロット
  • 学習15 分類による予測
    • 決定木, 二値分類, 剪定(pruning), 過学習(over fitting)
      • Data: kaggle titanic
    • k-近傍法(k-nearest neighbor method,kNN), 混同行列(Confusion matrix)
      • Data: kaggle digit-recognizer (MNIST)
  • 学習16 クラスタリングによる分類
    • (凝集型)階層的クラスタリング, デンドログラム(樹状図・樹形図)
    • 代表点(セントロイド)決定方法: 最短距離法,最長距離法,群平均法,ウォード法
      • Data: e-Stat 家計消費状況調査
    • k-means法(k平均法), k-means++法, エルボー法, SSE, シルエット図, シルエット分析
      • Data: UCI 卸売業者データ
    • アソシエーション分析, マーケットバスケット分析, 支持度,確信度,リフト値, アプリオリアルゴリズム
  • 学習17 ニューラルネットワークとその仕組み
    • AI, 自律性(Autonomy), 適応性(Adaptivity)
    • ニューラルネットワーク, 深層学習(Deep Learning)
    • 活性化関数, ステップ関数, パーセプトロン, シグモイド関数, ReLU(ランプ)関数, ソフトマックス関数
    • 損失関数, 勾配降下法(最急降下法), バックプロパゲーション(誤差逆伝播法)
    • Tool: TensorFlow Playground, Neural Network Console (SONY)
  • 学習18 テキストマイニングと画像認識
    • reCAPTCHA, OCR
    • テキストマイニング: MeCab, Word2vec
    • 物体検出: Tiny YOLO

いかがががががでしたか?

ここに出てくるキーワードがスラスラと説明できるようでなければ、データサイエンティストとしては厳しいかも。知らんけど。

ということで、このテキスト、これ系の仕事をしている人は一通り目を通すことをお勧めします。

「こんなこともわかんないの? 高校でもやる内容だよ!」と煽るのにも便利そうですね!

1 2 3 4 [ 次へ ]

たつをの ChangeLog
Powered by chalow