しばし投稿が途絶えてしまったが、この間、ベイズ統計を少し横に置いて、Rの重回帰分析やグラフィックスについて理解を深めた。今週末はPython基礎体力をつけるために、Python mode for processingに取り組んだ。
JavaとPythonの違い:
Pythonは動的に変数管理を行うため、Javaのようにいちいち変数の型を宣言しなくてもよいが、慣れないと本当に気持ち悪い。あとJavaやC言語などなどほとんどの言語は、とにかくカッコ{}で囲んで区切っていくが、Pythonはそのかわりに行インデントで規定する。そのため、インデントを間違えるとエラーコードを頂く。特にForループ文やIf Else文等の条件文では要注意。Javaに慣れてしまったJava脳では、Pythonは慣れないと本当にやりにくい。特にPythonの二次元配列(リストでしょうか)は、Java脳にとっては難しい。
Exporing and Explaining Data with the Processing Envirnment
「Processing による情報視覚化手法」
Let’s try to translate Java-based processing codes to Python-based codes!
Ch03-Mapping
1. Java: Step00_show_map.pde
1 2 3 4 5 6 7 8 9 10 11 |
PImage mapImage; void setup() { size(640, 400); mapImage = loadImage("map.png"); } void draw() { background(255); image(mapImage, 0, 0); } |
次にPython: Step00_show_map_py.pyde
1 2 3 4 5 6 7 8 9 |
def setup(): global mapImage size(640, 400) mapImage = loadImage("map.png") def draw(): global mapImage; background(255) image(mapImage, 0, 0) |
2. Java: step01_fig1_red_dots
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
PImage mapImage; Table locationTable; int rowCount; void setup() { size(640, 400); mapImage = loadImage("map.png"); // Make a data table from a file that contains // the coordinates of each state. locationTable = new Table("locations.tsv"); // The row count will be used a lot, store it locally. rowCount = locationTable.getRowCount(); } void draw() { background(255); image(mapImage, 0, 0); // Drawing attributes for the ellipses smooth(); fill(192, 0, 0); noStroke(); // Loop through the rows of the locations file and draw the points for (int row = 0; row < rowCount; row++) { float x = locationTable.getFloat(row, 1); // column 1 float y = locationTable.getFloat(row, 2); // column 2 ellipse(x, y, 9, 9); } } |
Table Class Table.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
class Table { int rowCount; String[][] data; Table(String filename) { String[] rows = loadStrings(filename); data = new String[rows.length][]; for (int i = 0; i < rows.length; i++) { if (trim(rows[i]).length() == 0) { continue; // skip empty rows } if (rows[i].startsWith("#")) { continue; // skip comment lines } // split the row on the tabs String[] pieces = split(rows[i], TAB); // copy to the table array data[rowCount] = pieces; rowCount++; // this could be done in one fell swoop via: //data[rowCount++] = split(rows[i], TAB); } // resize the 'data' array as necessary data = (String[][]) subset(data, 0, rowCount); } int getRowCount() { return rowCount; } // find a row by its name, returns -1 if no row found int getRowIndex(String name) { for (int i = 0; i < rowCount; i++) { if (data[i][0].equals(name)) { return i; } } println("No row named '" + name + "' was found"); return -1; } String getRowName(int row) { return getString(row, 0); } String getString(int rowIndex, int column) { return data[rowIndex][column]; } String getString(String rowName, int column) { return getString(getRowIndex(rowName), column); } int getInt(String rowName, int column) { return parseInt(getString(rowName, column)); } int getInt(int rowIndex, int column) { return parseInt(getString(rowIndex, column)); } float getFloat(String rowName, int column) { return parseFloat(getString(rowName, column)); } float getFloat(int rowIndex, int column) { return parseFloat(getString(rowIndex, column)); } void setRowName(int row, String what) { data[row][0] = what; } void setString(int rowIndex, int column, String what) { data[rowIndex][column] = what; } void setString(String rowName, int column, String what) { int rowIndex = getRowIndex(rowName); data[rowIndex][column] = what; } void setInt(int rowIndex, int column, int what) { data[rowIndex][column] = str(what); } void setInt(String rowName, int column, int what) { int rowIndex = getRowIndex(rowName); data[rowIndex][column] = str(what); } void setFloat(int rowIndex, int column, float what) { data[rowIndex][column] = str(what); } void setFloat(String rowName, int column, float what) { int rowIndex = getRowIndex(rowName); data[rowIndex][column] = str(what); } } |
Next, Python: step01_fig1_red_dots_py.pyde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import Table def setup(): global locationTable global mapImage global rowCount size(640, 400) mapImage = loadImage("map.png") locationTable = Table.Table("locations.tsv") rowCount = locationTable.getRowCount() print rowCount def draw(): global locationTable global mapImage global rowCount background(255) image(mapImage, 0, 0) noStroke() fill(192, 0, 0) for row in range(0,rowCount): x = locationTable.getFloat(row, 1) y = locationTable.getFloat(row, 2) ellipse(x, y, 9, 9) |
Table Class Table.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
class Table(): def __init__(self, filename): self.filename = filename self.rowCount = 0 self.rowsTable = loadStrings(self.filename) self.rowIndex = 0 self.pieces = [] self.data = [] self.data2 = [] self.value = 0 for i in range(len(self.rowsTable)): if len(self.rowsTable[i].strip()) == 0: continue if self.rowsTable[i].startswith('#'): continue self.pieces = split(self.rowsTable[self.rowCount], TAB) self.data = [self.pieces[i] for i in range (len(self.pieces))] self.data2.append(self.data) self.rowCount+=1 def getRowCount(self): return self.rowCount def getRowIndex(self, rowName): for i in range(self.rowCount): if (self.data2[i][0] == rowName): return i return -1 def getRowName(self, row): return self.data2[row][0] def getString(self, rowIndex, column): return self.data2[rowIndex][column] def getString2(self, rowName, column): for i in range(self.rowCount): if self.data2[i][0]==rowName: return self.data2[i][column] return -1 def getInt(self, rowIndex, column): return int(self.data2[rowIndex][column]) def getInt2(self, rowName, column): for i in range(self.rowCount): if (self.data2[i][0].equals(rowName)): return int(self.data2[i][column]) return -1 def getFloat(self, rowIndex, column): return float(self.data2[rowIndex][column]) def getFloat2(self, rowName, column): for i in range(self.rowCount): if (self.data2[i][0]==(rowName)): return float(self.data2[i][column]) return -1 def setFloat(self, rowIndex, column, what): self.data2[rowIndex][column] = str(what) def setFloat2(self, rowName, column, what): rowIndex = getRowIndex(self, rowName) self.data2[rowIndex][column] = str(what) |
3. step02_fig2_varying_sizes.pde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
PImage mapImage; Table locationTable; int rowCount; Table dataTable; float dataMin = MAX_FLOAT; float dataMax = MIN_FLOAT; void setup() { size(640, 400); mapImage = loadImage("map.png"); locationTable = new Table("locations.tsv"); rowCount = locationTable.getRowCount(); // Read the data table dataTable = new Table("random.tsv"); // Find the minimum and maximum values for (int row = 0; row < rowCount; row++) { float value = dataTable.getFloat(row, 1); if (value > dataMax) { dataMax = value; } if (value < dataMin) { dataMin = value; } } } void draw() { background(255); image(mapImage, 0, 0); smooth(); fill(192, 0, 0); noStroke(); for (int row = 0; row < rowCount; row++) { String abbrev = dataTable.getRowName(row); float x = locationTable.getFloat(abbrev, 1); float y = locationTable.getFloat(abbrev, 2); drawData(x, y, abbrev); } } // Map the size of the ellipse to the data value void drawData(float x, float y, String abbrev) { // Get data value for state float value = dataTable.getFloat(abbrev, 1); // Re-map the value to a number between 2 and 40 float mapped = map(value, dataMin, dataMax, 2, 40); // Draw an ellipse for this item ellipse(x, y, mapped, mapped); } |
step02_fig2_varying_sizes_py.pyde
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
import Table dataMin = 0 dataMax = 0 def setup(): global locationTable global mapImage global rowCount global dataTable global dataMin global dataMax size(640, 400) mapImage = loadImage("map.png") locationTable = Table.Table("locations.tsv") rowCount = locationTable.getRowCount() dataTable = Table.Table("random.tsv") # Find the minimum and maximum values for row in range(rowCount): value = dataTable.getFloat(row, 1) if value > dataMax: dataMax = value if value < dataMin: dataMin = value def draw(): global locationTable global mapImage global rowCount global dataTable global dataMin global dataMax background(255) #print(rowCount) image(mapImage, 0, 0) fill(192, 0, 0) noStroke() for row in range(0,rowCount): abbrev = dataTable.getRowName(row) x = locationTable.getFloat2(abbrev, 1) y = locationTable.getFloat2(abbrev, 2) drawData(x, y, abbrev) # Map the size of the ellipse to the data value def drawData(x, y, abbrev): global dataTable global dataMin global dataMax #Get data value for state value = dataTable.getFloat2(abbrev, 1) #Re-map the value to a number between 2 and 40 mapped = map(value, dataMin, dataMax, 2, 40) #Draw an ellipse for this item ellipse(x, y, mapped, mapped) |