kukkuのメモ帳

勉強したこと,思ったこと,あったことをつらつら書いていきます

Python初心者がGoogleフォームの結果を集計する

みなさんお久しぶりです。くっくです。

今回はGoogleフォームを集計する話です。 GoogleフォームはGoogleDriveの一種で、アンケートを作れるやつです。アンケート結果はGoogleスプレッドシートで見ることができます。

生成されるスプレッドシートはこんな感じ

タイムスタンプ 性別 好きな食べ物 自転車乗れる?
20XX/0X/XX 00:00:00 男性 りんご YES
20XX/0Y/YY 00:00:00 男性 みかん, オレンジ NO
20XX/0Z/ZZ 00:00:00 女性 バナナ YES

3人ぐらいなら問題ないんですが、これが100人とか200人とかになると、「りんごが好きなのは何人だろう」とか「みかんが好きなら自転車に乗れないかが知りたい」とかのためにいちいち指折り数えるのは非常にしんどいです。 GoogleスプレッドシートExcelで開くことができますが、それでも面倒です。僕はできませんでした。

ならコードでやろう!なにでやろう?Pythonだ!!

と思い立ち、これまで全く使ったことのないPythonで集計することにしました。

目標

  1. 各質問内容に対し回答内容とその数をカウントする。
  2. ある質問が特定の回答の場合のみカウントする。

環境

勉強

Pythonでやろうと思い立ったはいいものの、文法とか全く知りません。こんな時は

dotinstall.com

定番ですね。何かを始めるときは毎回お世話になっています。今まで見たやつを全部メモに残してたのに、すべて消えたのがショックでなりません。

とりあえず、これを全部見て感覚を掴みます。

書いていこう

書いていきます。

準備

GoogleDriveから回答のスプレッドシートをダウンロードします。勝手にExcel形式に変換されて落ちてきます。

ダウンロードできたらファイルを開き、「名前をつけて保存」からCSVに変換します。 このままでもいけなくはないらしいですが、今回はCSVからやってみます。

読み込み

CSVを読み込みます。そのまま

import csv
f = open("ファイル名.csv", 'r')

として読み込むと、文字化けやら文字コードがそのままでてくるやらで大変でした。そこで、

import csv, codecs
f = open(u"ファイル名.csv", 'r', encoding='utf-8')

respondents = csv.reader(f)
header = next(csv.reader(f))

ってやると上手く読み込めます。respondentsには回答が、headerには質問内容(上表の1行目)が入ります。

また、読み込む前にCSV文字コードUTF-8に変換しておきましょう。 いまいちPythonでのやり方がわからなかったので、ターミナルでnkf -w --overwrite ファイル名ってするなり、好きなエディタの文字コード変換機能を使うなりすればいいと思います。

集計(1)

さて、やっと本題です。 リストの内容をカウントしていくわけですが、便利なライブラリがあります。名前はそのまんま「Counter」です。

from collections import Counter
cnt = Counter()

for i in range(len(header)):
    cnt[header[i]] = Counter()

とすることで、各質問内容に対するカウンターが定義されます。 回答者が1人だけなら、というか、リストが1重ならfor文以下は不要です。

あとは

for respondent in respondents:
    for i in range(len(header)):
        cnt[header[i]][respondent[i]] += 1

とすれば、カウンタcntの中に各質問の回答とその個数が辞書型で格納されています。便利ですね。

ですが、このままだとちょっとした問題があります。複数回答の扱いです。Googleフォームの複数回答CSVで見ると

…, "みかん, オレンジ", …

といったようにダブルクオーテーションで囲まれ、2つがセットになって1つとカウントされます。つまり、みかんとオレンジが好きな人、みかんとバナナが好きな人、みかんだけが好きな人は別扱いです。

ここで、みかん好きが3人とカウントされるようになるためには

for respondent in respondents:
    for i in range(len(header)):
        ress = respondent[i].split(", ")
        for res in ress:
            cnt[header[i]][res] += 1

2行目と3行目が追加したところです。セットになってるところも「, 」で区切られているので、これを無理矢理分割してリストに格納し、そのリストのそれぞれについてカウントします。

これで、複数回答にも対応した各質問の回答とその数を数えることが出来ました。

集計(2)

次は、ある質問に対して特定の回答だった場合のみカウントするようにします。 といっても

for respondent in respondents:
    # 追加
    if respondent[3] == "YES":
        continue

    for i in range(len(header)):
        ress = respondent[i].split(", ")
        for res in ress:
            cnt[header[i]][res] += 1

2, 3行目を追加しただけです。 3つ目の質問が「YES」であった時、集計をスキップします。

出力

集計結果をCSVファイルに出力していきます。

まず準備を

ff = codecs.open("ファイル名.csv", 'w', encoding='shift-jis')
csvWriter = csv.writer(ff)

わざわざshift-jisで出力しているのは、こうしないとExcelで文字化けして見れないからです。面倒くさいですね。

書き込んでいきましょう。

for i in range(len(cnt)):
    # 初期化
    question = []
    answer = []
    ansNum = []

    # 質問名書き込み
    question.append(header[i])

    # keys()はdect_keys型で返るのでlistに変換
    keys = list(cnt[header[i]].keys())
    for j in range(len(cnt[header[i]])):
        # 回答書き込み
        answer.append(keys[j])
        # 回答数書き込み
        ansNum.append(cnt[header[i]][keys[j]])

    # ファイルに書き込み
    csvWriter.writerow(question)
    csvWriter.writerow(answer)
    csvWriter.writerow(ansNum)

以上です。質問、回答、回答数がCSVファイルに質問個数分繰り返し書き込まれます。csvWriterの部分はなんかまとめて書く方法があった気がしますが、これでいけたのでいいことにしました。ごめんなさい。

まとめ

Googleフォームの結果を集計する話はいかがでしたでしょうか。 活用いただければ幸いです。

「いやお前こうしろよ」っていうツッコミもガンガンお願いします。

それでは。

[追記]

作成したプログラムのGistを公開しました。

gistcb7d4ff663d8345e47b2

LCC比較 Jetstar & Peach

はじめに

みなさんこんにちは.くっくです.

先日の記事は読んでいただけたでしょうか. ぜひXcodeを開いて実際に試してもらえると嬉しいです. kukku2123.hatenablog.com

さて,今回は飛行機,それもLCCの話題です. 僕は飛行機での移動にJetstarというLCC(格安空港会社)を使うことがほとんどだったのですが,先日初めてPeachを使ってみました.

せっかくなので,この2社を比較してみたいと思います.

注意

  • あえて何も参考にせず主観のみで書きます.間違ってる点などあれば指摘お願いします.
  • 関西空港 - 新千歳空港の場合のみです.それしか乗ってないので.

搭乗まで

関西空港の場合,Peachは第二ターミナルまで行く必要がある. 連絡バスで5分程度.めんどい.

ご飯を食べる場合は第一ターミナルですましたほうが良い.

機内

サービス的な何かは当然なし.

座席はPeachの方がややしっかりしていた.……が,先日の帰りの便はおそらくJetstarと同じ,後ろの人がゴソゴソしたら背中にダイレクト感触の伝わる座席だった.

また,Jetstarは,日本語での放送(?)のあと英語で同じ内容を話していたが,Peachは日本語のみだった.

値段

時間・時期を考えなければJetstarが最も安い.平日朝8時に乗ったりすると関西空港から往復1万程度で北海道に上陸できる.安すぎ.

逆に,人気のある時間・時期はLCCとは思えない値段になったりする.早めの予約が吉.

Peachは,最安便はJetstarと比べると若干高いが,人気のある昼間や休日でも値段の上げ幅がやや小さい印象.

おわりに

LCC比較はどうでしたでしょうか.

比較的時間に余裕があり,とにかく安く行きたい人にはJetstarを, 休日や,人気のありそうな時間に乗りたい人はPeachを選べばいいのではないでしょうか.

できるだけ安く飛行機に乗りたい人の参考になれば幸いです.

それでは.

最短でiOSアプリを動かすところまで

はじめに

みなさんはじめまして.くっくです.

去年まで高専生でしたが,今年度から大学生になりました.

最近Swiftを始めたので,これの勉強記事が中心になると思います.初心者ですよ.なんかできそうなブログタイトルですが初心者ですよ.はい.

それではせっかくなので,タイトルどおりiOSアプリを最短で動かすところまで書こうと思います.目標は5分です. Xcodeない人(というかMac持ってない人)は申し訳ないけどUターンだよ!

プロジェクトの作成

  1. Xcodeを開き,[File]→[New]→[Project]を選択.
  2. [iOS]→[Application]→[Single View Application]を選択.これがプロジェクトテンプレートになります.
  3. てきとーに入力して,てきとーに保存する.どうせ公開しないので考えないでOK.

これで準備はできました.

初期設定

言語設定とか対象バージョン設定とかはした方がいいけど,今回はお試しだし,最短で作るので飛ばします.

UI配置

画面左側の[Main.storyboard]を選択すると下みたいな感じの画面に移ります. f:id:kukku2123:20150414005020p:plain

この状態で,画面右下の検索バーで[Web]と打てば,その上に[Web View]が出てきます.

それをドラッグして,画面真ん中のiOSっぽい画面のところにドロップしてください.とりあえずUIの配置は以上.絶対足りないけどね!

書く

最低限の実装をしていきます.

画面右上の,丸が2つ重なったアイコンをクリックして,[Main.storyboard]と[ViewController.swift]を同時に表示させてください.

そして,[View Controller Scene]の下層にある[Web View]をcontrolを押しながらドラッグし,エディタ部分のViewController クラス内にドロップします.

ダイアログが出てくるので,nameに「webView」とでも書いてConnectします. これで作成したビューにアクセスすることができます.

あとは,すでに作成されてるviewDidLoad関数の中に

override func viewDidLoad() {
    super.viewDidLoad()
    openUrl("http://hatenablog.com/")
}

と追記して,クラス内のどっかに

func openUrl(urlString: String){
    let url = NSURL(string: urlString)
    let urlRequest = NSURLRequest(URL: url!)
    webView.loadRequest(urlRequest)
}

って書いたら終了.openUrlの引数は好きにして.

動かす

画面右上でてきとーなiOS機器を設定し,実行するとf:id:kukku2123:20150414012400p:plain

はい,動きました. なにを作ったかというと,まあみなさん気づいていると思いますが,戻るボタンすらない,ただWebを見るだけのアプリです.

UIの設定を何もしてないので,上の方にまだ要素があったり下が余ったりしてます. それでもこれだけでiOSアプリが作れました.なんか作るの大事.しょぼいけど.

おわりに

というわけで,5分ぐらいでiOSシュミレーターを動かすところまで行くのを目標に書いてみました.

振り返るとさすがにショボすぎるので,今度はもうちょいUIをちゃんとしたいと思います.

以上.