ZawaWorks’s diary

プログラミング技術メモ

Python : pandasでdf['hoge']が使えないときの対処法

はじめに

自分の研究でデータ分析をするためにpandasを使い始めました.pandasはcsv(tsv)ファイルをdf = pd.read_csv('hoge.csv')(またはread_table)で読み込んで,df['hoge'] という形で指定したカラム(列)を配列として抽出できます.しかし,あるときなぜかそれができませんでした.そこで,そのときの対処法をここでまとめました.

今日使うデータの説明

今回使うデータは以下の通りです.

hoge.csv

id sex name
0 M Yuta
1 F Rikka
2 M Sho

ちなみに表の一番上にあるid, sex, nameのタイトルが書かれているカラムのことをヘッダーといいます.

コード

df pd.read_csv('hoge.csv')

print(df['id'])
print(df['sex'])
print(df['name'])

これがうまくいけば以下のような結果が返ってきます.

実行結果

[0, 1, 2]
[`M`, `F`, `M`]
[`Yuta`, `Rikka`, `Sho`]

read_csvかread_tableかを確認

pandasには 'read_csv' と read_table という二つの命令があります.これらは前者がcsvファイルを読み込むときに使い,後者が read_table ファイルを読み込むときに使います.

read_csv read_table
csv専用 tsv専用

そのため,read_csv('hoge.tsv')read_table('hoge.csv') とすると,ヘッダーが読み込めなくなり,df['id']と呼んでも[0, 1, 2] の配列は返ってきません. ちゃんとread_csv('hoge.csv')read_table('hoge.tsv')になっているか確認しましょう.

index_col=0 またはheader=0を入れる

たとえばread_csv('hoge.csv')をやってもdf['id']が出ない場合,hoge.csvが「ヘッダーがないcsvファイル」として読み込まれている可能性があります.csvファイルには「ヘッダーあり」の場合とありますと「ヘッダーなし」の場合があります.df['id']でカラムを抽出できるのは,ヘッダーありcsvの場合なので,ヘッダーがないcsvだとできません.このとき,ヘッダーありのcsvとして読み込むためには,以下のように書きます.

df = pd.read_csv('hoge.csv', index_col=0)
df = pd.read_csv('hoge.csv', header=0)

index_col = 0は「0行目をindexとして使いますよ」という変数で,header=0は「0行名をヘッダーにするよ」という命令です.これを指定あげることで,「0行目がヘッダーのcsvファイル」として読み込むことができます.

Processing : PGraphicsでジェネラティブアート

はじめに

私はProcessingを使ってジェネラティブアートを作るのが趣味です.作っていくうちに「 PGraphics 使うといろんな作品が作れる!」と気づいたので紹介します.

PGraphicsの簡単な紹介

PGraphicsは簡単に言うとProcessing画面を画像として作り出すものです.

実行画面

youtu.be

コード

gist.github.com

このように beginDraw() と, endDraw() の間にProcessingでおなじみの background()ellipse() , rect() などの命令を書き込むことでPGraphics内を描画します.そして,描画されたPGraphicsは image() を使って,PImageと同じように使うことができます.

我流:PGraphicsの使い方

パネルの中だけ色違いにする

画面中心に白い円があります.この円をマウスで動かすPGraphics上だけ背景と円の色が違うようにしたいと思います.

実行画面

youtu.be

コード

gist.github.com

仕組み

次の図の赤い点はPGraphicsの左上の座標,緑の点は ellipse() の中心を表しています.

Processing画面の目線

f:id:ZawaWorks:20181207003950p:plain
PGraphicsの左上の座標を (pgX, pgY) ,円の中心を (250, 250) とします.このとき (pgX, pgY)(250, 250) の距離は (250-pgX, 250-pgY) あります.

PGraphicsの目線

f:id:ZawaWorks:20181207004248p:plain 先ほどの図をPGraphicsの目線で見ます.PGraphicsの左上の座標を (0, 0) とすると,円の中心は (250-pgX, 250-pgY) になります.このようにPGraphicsの目線で見ると,オブジェクトの座標はすべて (-pgX, -pgY) を足して表すことができるのです.

作品例

では,これを使ってジェネラティブアートしていきます.

作品1:市松模様

左上から交互に背景と円が白黒逆転したPGraphicsを並べます.円の位置はランダムで決めて,それぞれのPGraphics上でも円を描いています.だから,同じ円なのに部分ごとに色が違っていきます.

作品2:揺れる文字

今までのような PGraphicsの使い方をすると,Processing画面上の図形とPGraphics上の図形が一致します.PGraphics上の図形の位置を少しずらすとまるで図形が歪んだように見えます.これを文字でやってみたら結構エモくなりました.

おわりに

今回は私が発見した「PGraphicsアート」の紹介をしました.この手法を使った作品をいろいろ考案しているところです.よろしければこの手法を使ってみてください.これを読んだ皆さんがこの手法でどんな作品を作るか楽しみにしています!

Adobe Premiere Proでオブジェクトを回転運動させる方法

はじめに

動画編集のために Adobe Premiere Pro を使ったのですが,そこで「オブジェクトの回転運動」で手こずったので,そのときの対策を書き記しておきます.

今回の目標

下の動画のようにカーソルをその向きのまま回転させます. カーソルは1秒に360度回転させています.

www.youtube.com

普通に回転運動をさせようとすると

オブジェクトを回転するときの操作はこうです この操作でカーソルの画像を回転させてみましょう

www.youtube.com

なんと向きまで変わってしまいました.

対策

このときの対策は,オブジェクト自体を動かしたい方向と逆回転させ,そのシーケンスを動かしたい方向に回転させればいいのです

www.youtube.com

やったことは

  1. カーソル自体は1秒間で-360度で回転させる
  2. そのカーソルをネストしたシーケンスにする
  3. そのシーケンスを1秒間で360度に回転させる

このようにn秒間でm度回転させたいときは,そのオブジェクト自体はn秒間に-m秒間すれば大丈夫になります!

おわりに

自分はこの方法で対策しましたが,他にもっと良い方法があったら教えてくれるとありがたいです.

Processing: 正弦波を使ったおもしろ図形(おにぎり、花、金平糖、その他)

はじめに

Processingで正弦波を使って様々な図形を作ってみました。すべて同じ関数の変数をいじるだけで作成できます。

使う関数

今回使う関数はwave_circle()という自作の関数です。この関数は元々ジグザグした円を作るために作成しました。

wave_circle()

void setup() {
  size(600, 600);
  fill(-1);
  wave_circle(width/2, height/2, 100, 10, 10);
}

//posX,posY: 座標, r: 半径, wavelength: 波長(波の幅), amplitude: 振幅(波の高さ)
void wave_circle(float posX, float posY, float r, float wavelength, float  amplitude) {
  pushMatrix();
  translate(posX, posY);

  beginShape();
  for (float i=0; i <= 2*PI; i += PI/180) {
    float x = cos(i)*( r + amplitude*sin(i*wavelength) );
    float y = sin(i)*( r + amplitude*sin(i*wavelength) );

    vertex(x, y);
  }
  endShape();

  popMatrix();
}

出力結果

f:id:ZawaWorks:20180509233417p:plain 上の図のように金平糖のようなジグザグした図形を作ることができます。これで目的は達成したのですが、変数をいじってみたら様々な形に変わることが分かりました。

図形一覧

ここからはどのような変数を入れるといかなる図形になるの一覧にしました。

金平糖

wavelength = 10 , amplitude = r/10 f:id:ZawaWorks:20180509233417p:plain

ミートボール

wavelength = 20, amplitude = r/100 f:id:ZawaWorks:20180509234412p:plain

ウニ

wavelength = 100, amplitude = r/10 f:id:ZawaWorks:20180509235117p:plain

おにぎり(角丸多角形)

wavelength = 3, amplitude = r/10wavelength = n のとき角丸のn角形になります) f:id:ZawaWorks:20180509235657p:plain

花びら

wavelength > 2, amplitude = r (図はwavelength = 5のとき) f:id:ZawaWorks:20180509235912p:plain

ヒトデ、星

wavelength = 5, amplitude = (3*r) / 10 f:id:ZawaWorks:20180510000204p:plain

作品事例

この関数を使って作ってみた作品です。

おわりに

なんとなく作ってみた関数でいろいろな図形を描くことができたことに驚きました。なんとなく入れた数字で想像してなかった図形に巡り合えることが興味深かったです。もしかしたら僕も発見してない図形があるかもしれないので試してみると面白いかもしれません。

ArduinoからProcessingに複数のint型データを送る

はじめに

最近、Arduinoを使って複数の曲げセンサの値をProcessingに送り、ある値になると音を出すというものを作りました。このときArduinoで取得したint型のデータをProcessingに送信することに苦戦したのでその対処法をまとめました。

そもそもなんで上手くint型のデータを送れないの?

ArduinoからProcessingへint型のデータを送る - Imaginable Realityによると実際にArduinoから送っているデータは2バイトですが、シリアル通信では1バイトずつ送っているため2バイト以上のデータの処理に工夫がいるようです。

対処法

今回はString型として受信して処理する方法を書きます。 以下のコードは3つのint型の値をProcessingに送るコードです。

void setup() {
  Serial.begin(9600);  // シリアル通信速度
}

void loop() {
    Serial.print(777);
    Serial.print(",");
    Serial.print(888);
    Serial.print(",");
    Serial.print(999);
    Serial.print("\n");

  }


  // 1秒待機
  delay(1000);
}

そして、Arduinoから受け取った値を取得するProcessingのコードです。

import processing.serial.*;
Serial myPort;

int []data = new int [3];
 
void setup() {
  myPort = new Serial(this, Serial.list()[0], 9600);
}

void draw(){}

//送られてきたデータを処理する関数
 void serialEvent(Serial p) {  
   String inString = myPort.readStringUntil('\n');
 
   if (inString != null) {
     inString = trim(inString);
     data = int(split(inString, ','));
     println(data);//受信したデータ配列を参照
   }
 }

命令の解説

注目するのは以下の関数です。

 void serialEvent(Serial p) {  
   String inString = myPort.readStringUntil('\n');
 
   if (inString != null) {
     inString = trim(inString);
     data = int(split(inString, ','));
     println(data);//受信したデータ配列を参照
   }
 }

ステップ①

String inString = myPort.readStringUntil('\n'); は送られたデータの \nまでを受け取ります。

受信したデータ(isString)

"777,888,999\n"

ステップ②

そして、trim()を使うことで文字列から改行(\n)を削除します。

受信したデータ(isString)

"777,888,999"

ステップ③

次にsplit()を使って,で区切られた文字列を配列として抜き出します。

受信したデータを文字列配列にする

{"777", "888", "999"}

ステップ④

最後にint()を使ってint型の配列にします。

int型の配列にする

{777, 888, 999}

こうしてArduinoからProcessingに3つのint型のデータを送ることができました。

おわりに

Arduinoからint型を受け取るには送られてきたバイトのデータからint型に復元するというやり方がありましたが、こっちのほうが初心者でも理解しやすいし、覚えやすいような気がしました。

参考資料

d.hatena.ne.jp [Arduino->Processing]ArduinoからProcessingへ複数のデータを送信テスト①m0rya.wordpress.com ch.nicovideo.jp

p5js:スマホのブラウザ上でmouseX,mouseYが使えない問題と解決法

はじめに

p5jsを使って簡単なお絵描きツールを作ろうとしたのですが、PC上ではマウスで線を描画できたのに、スマホ上ではタッチで線を描画することができませんでした。今回はその問題の解決法を紹介します。

環境設定

PC上でのコード

PCのブラウザ上でマウスを使い線を描画するため、index.htmlを用意しました。

index.html

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width">
    <script language="javascript" type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.2.9/p5.min.js"></script>
<body>
    <script>
    / /p5js

       function setup() {
            createCanvas(displayWidth, displayHeight);
            background(255);

            strokeWeight(10)
            stroke(0);
        }

        function draw() {}

        function mouseDragged() {
            line(mouseX, mouseY, pmouseX, pmouseY);
            return false;
        }
  </script>
</body>

</html>

これを実行したすると次の動画のようになります。

youtu.be

スマホ上のコード

解決までの経緯

これをNode.jsでサーバを立ててスマホ上で開いてみます。server.jsindex.htmlと同じフォルダーに入れてください。

server.js

var http = require('http'),
    fs = require('fs');
var server = http.createServer();
var ipadress = "";//pcのipアドレスを書く
var port = 3000;//ポート番号

server.on('request', function (req, res) {
    fs.readFile(__dirname + '/indext.html', 'utf-8', function (err, data) {
        if (err) {
            res.writeHead(404, { 'Content-Type': 'text/plain' });
            res.write("not found!");
            return res.end();
        }
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.write(data);
        res.end();
    });
});
server.listen(port, ipadress);
console.log("server listening ...");

これをnode serverで実行してスマホのブラウザで読み込みました。しかし、なぜか描画できない……。 調べてみるとどうやらp5jsにはtouchMoved()という関数が定義されており、スマホ上ではそちらを使うようです。そして、touchMoved()を使って線を描画するサンプルがあったのでindex.htmlの中身を変えてみました。

index.htmlのp5jsコードの部分

 function setup() {
    createCanvas(displayWidth, displayHeight);
    strokeWeight(10)
    stroke(0);
}

function touchMoved() {
    line(mouseX, mouseY, pmouseX, pmouseY);
    return false;
}

p5.js | examplesより引用

しかし、どれだけタッチしてもmouseXmouseYも値が0のままで、PC上のような描画ができませんでした。

解決方法

さらに調べてみるとtoutchesという配列がp5jsで定義されているようです( (p5:touches)https://p5js.org/reference/#/p5/touches

)。これはスマホのタッチデバイスで検出した指の本数分の座標を格納する配列です。これ使い、コードを書き直しました。

index.htmlのp5jsコードの部分

        var ptouchX;
        var ptouchY;

        function setup() {
            createCanvas(displayWidth, displayHeight);
            background(255);

            strokeWeight(10)
            stroke(0);

        }

        function draw() {
            ptouchX = touches[0].x;
            ptouchY = touches[0].y;
        }

        function touchMoved() {
            line(touches[0].x, touches[0].y, ptouchX, ptouchY);
            return false;
        }

youtu.be

すると見事に動きました!

最終的なコード

sketch.html · GitHub

おわりに

p5jsがマウスイベントとタッチイベントを全く別に定義していることを知らなかったため、PC上で動いたコードがスマホ上で動かなかったときは大変驚きました。p5jsは簡単にスマホ向けWebアプリを作れて便利ですので、皆さんもぜひ使ってみてください。

Node.jsでサーバーを立ててngrokで外部公開

はじめに

Node.jsでサーバーを立てて、htmlファイルを読み込むとき、ローカルホストではなく外部からURLを開くと自分のPCのIPアドレスがバレバレになってしまいます。今回は、それを防ぐために、ngrokというサービスを使った話をします。

Node.jsでサーバを立てる

同じフォルダー内にserver.jsindex.htmlを作ります。

sever.js

var http = require('http'),
    port = 3000,//ポート番号
    ipadress = 'localhost',//IPアドレス
    fs = require('fs');


var server = http.createServer();

server.on('request', function (req, res) {
    fs.readFile(__dirname + '/index.html', 'utf-8', function (err, data) {
        if (err) {
            res.writeHead(404, { 'Content-Type': 'text/plain' });
            res.write("not found!");
            return res.end();
        }
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.write(data);
        res.end();
    });
});

server.listen(port, ipadress);
console.log("server listening ...");

index.html

<!DOCTYPE html>
<html>

<head>
</head>

<body>
    Hello,world!
</body>

</html>

そうしたらコマンドラインを開いて、そのフォルダー内でnode serverとコマンドを打ちます。 そして、ブラウザでhttp://localhost:3000/を開いてください。下の画像のようになったら成功です。 f:id:ZawaWorks:20171225225338p:plain

ngrokで外部に公開

ngrokをインストールするとngrokコマンドが使えるようになります(ngrokのインストール方法)。 Node.jsでサーバを立てたら、以下のコマンドを打ってください。

ngrok http 3000

ここでの3000server.jsで指定したポート番号です。 そうすると以下のような結果が返ってきます。 f:id:ZawaWorks:20171225230017p:plain 上の画像の赤線を引いたURLをブラウザで開いてください。 f:id:ZawaWorks:20171225230156p:plain そうするとローカル環境のサイトであるindex.htmlが外部で公開できていることが分かります。