2013-04-15
subdivisionjp.R
subdivisionjp.zip (Download page at Google Drive)
Documentation
http://rpubs.com/ogura/5493
(Update: 2013-04-16 22:50 JST)
I didn't know of package Nippon, which includes prefectures table and many other useful features.
I wonder if you should have Unicode data in Unicode character codes like "<U+6771><U+4EAC><U+90FD>" instead of "東京都".
If you have original data in Unicode characters like "<U+6771><U+4EAC><U+90FD>", R console outputs text in a readable way, but the original data itself is less human-readable.
If you have original data directly put like "東京都" (I don't know the name of representation), the original data is human-readable, but console outputs garbled text.
Converting principal subdivision names in Japan
Replacing Japanese characters with Roman notations manually is a very tedious task that many people may not want to do.
Commonly used names like principal subdivisions, or prefecture (the United States' counterparts are states), among others, would be handy if you can get their Roman notations quickly.
So I made a script to convert names of Japan's principal subdivisions between Japanese (Kanji) and Roman.
iso3166-2jp (Google Apps Script. I don't know why, but Google sign-in is required to view the code though I'm sharing it for anonymous access.)
If you make a copy of the above script and include it as a library, you can use its functions in your Google Sheets.
Japan's principal subdivisions:
http://en.wikipedia.org/wiki/ISO_3166-2:JP
http://ja.wikipedia.org/wiki/ISO_3166-2:JP
2013-03-21
JavaScript: Feedly feeds extractor bookmarklet
(2nd update, March 21, 2013, 21:58 JST: bug fix and JSON/OPML option added.)
(3rd update, March 21, 2013, 22:17 JST: change names of some keys in JSON.)
Feedly is a great feed reader, but it doesn't seem to have an export function.
So I created a bookmarklet to extract URLs of your feed subscriptions and their categories and output them in JSON/OPML format.
Feedly feeds extractor bookmarklet
This bookmarklet only works at your Feedly index page (http://www.feedly.com/home#index).
After running this code, a text area containing the JSON data will be created at the bottom of the page.
Pretty-printed version:
// Feedly feeds extractor bookmarklet by Toshiyuki Ogura
// Run this code at http://www.feedly.com/home#index
// A text area containing your feed urls in JSON format will be created at the bottom of the page.
javascript:(function(){
if (window.location.href != 'http://www.feedly.com/home#index') {
} else {
function docEvaluateArray (expr, doc, context, resolver) {
doc = doc ? doc : (context ? context.ownerDocument : document);
resolver = resolver ? resolver : null;
context = context ? context : doc;
var result = doc.evaluate(expr, context, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var a = [];
for(var i = 0; i < result.snapshotLength; i++) {
a[i] = result.snapshotItem(i);
}
return a;
}
/*
// This function doesn't work because of HTMLUnknownElement.
function jsonToOPMLString (jsonObj) {
var xmlDeclaration = '<?xml version="1.0" encoding="utf-8"?>';
var opmlElement = document.createElement('opml');
opmlElement.setAttribute('version', '1.0');
var headElement = opmlElement.createElement('head');
headElement.createElement('title');
headElement.createElement('dateCreated');
headElement.createElement('dateModified');
headElement.createElement('ownerName');
headElement.createElement('ownerEmail');
var bodyElement = opmlElement.createElement('body');
for (var i = 0; i < jsonObj.length; i++) {
var categoryOutline = bodyElement.createElement('outline');
categoryOutline.setAttribute('text', jsonObj[i]['categoryName']);
for (var j = 0; j < jsonObj[i]['feeds'].length; j++) {
var feedObj = jsonObj[i]['feeds'][j];
var urlOutline = categoryOutline.createElement('outline');
urlOutline.setAttribute('text', feedObj['title']);
urlOutline.setAttribute('type', 'link');
urlOutline.setAttribute('xmlUrl', feedObj['xmlUrl']);
}
}
return xmlDeclaration + opmlElement.innerHTML;
}
*/
function jsonToOPMLString (jsonObj) {
var newLine = '\n'; // for pretty-printing
function getTagString(tagName, text, attrArray) { // attrArray = [['attr1', 'val1'], ['attr2', 'val2']];
var attrStringArray = [];
if(attrArray) {
for (var i = 0; i < attrArray.length; i++) {
attrStringArray.push(attrArray[i][0] + '="' + attrArray[i][1] + '"');
}
var result = '<' + tagName + ' ' + attrStringArray.join(' ');
} else {
var result = '<' + tagName;
}
if (text) {
if (text[0] == '<') {
return result + '>' + newLine + text + '</' + tagName + '>' + newLine;
} else {
return result + '>' + text + '</' + tagName + '>' + newLine;
}
} else {
return result + '/>' + newLine;
}
}
var categoryArray = [];
for (var i = 0; i < jsonObj.length; i++) {
var feedsArray = [];
for (var j = 0; j < jsonObj[i]['feeds'].length; j++) {
var outlineFeed = getTagString('outline', undefined,
[ [ 'text', jsonObj[i]['feeds'][j]['title'] ],
[ 'title', jsonObj[i]['feeds'][j]['title'] ],
[ 'type', 'rss' ],
[ 'xmlUrl', jsonObj[i]['feeds'][j]['xmlUrl'] ] ]);
feedsArray.push(outlineFeed);
}
var outlineCategory = getTagString('outline', feedsArray.join(''),
[ [ 'text', jsonObj[i]['category'] ],
[ 'title', jsonObj[i]['category'] ] ]);
categoryArray.push(outlineCategory);
}
var titleTag = getTagString('title', 'My Feedly feeds');
var nowTimeString = new Date().toUTCString();
var dateCreatedTag = getTagString('dateCreated', nowTimeString);
var dateModifiedTag = getTagString('dateModified', nowTimeString);
var ownerNameTag = getTagString('ownerName', 'My name');
var ownerEmailTag = getTagString('ownerEmail', 'My email');
var headTag = getTagString('head', titleTag + dateCreatedTag + dateModifiedTag + ownerNameTag + ownerEmailTag);
var bodyTag = getTagString('body', categoryArray.join(''));
var opmlTag = getTagString('opml', headTag + bodyTag);
var xmlDeclaration = '<?xml version="1.0" encoding="utf-8"?>' + newLine;
return xmlDeclaration + opmlTag;
}
var bulk = docEvaluateArray("//div[@id='mainArea']/div[starts-with(@class,'cell')]");
var items = Array.prototype.slice.call(bulk[0].childNodes);
for (var i = 1; i < bulk.length; i++) {
var arrayTemp = Array.prototype.slice.call(bulk[i].childNodes);
items = items.concat(arrayTemp);
}
var groupsArray = [];
var categoryObj = {};
var feedsArray = [];
for (var j = 0; j < items.length; j++) {
if (items[j].nodeName == 'H2') {
if (categoryObj['category'] == undefined) {
categoryObj['category'] = items[j].innerHTML.replace(/^\s*/, '').replace(/\s*$/, '');
} else {
categoryObj['feeds'] = feedsArray;
groupsArray.push(categoryObj);
categoryObj = {};
feedsArray = [];
categoryObj['category'] = items[j].innerHTML.replace(/^\s*/, '').replace(/\s*$/, '');
}
} else if (items[j].nodeName == 'DIV') {
var feedObj = {'title' : items[j].childNodes[2].nodeValue.replace(/^[\s\n]*/g, '').replace(/[\s\n]*$/g, ''),
'xmlUrl' : items[j].getAttribute('data-uri').replace('subscription/feed/','') };
feedsArray.push(feedObj);
}
}
var result = document.createElement('textarea');
result.setAttribute('rows', '10');
result.setAttribute('cols', '100%');
document.querySelector('div#mainBar').appendChild(result);
var choice = confirm('Press OK to get JSON,\nCancel to get OPML');
if (choice) {
result.value = JSON.stringify(groupsArray, undefined, 2);
} else {
result.value = jsonToOPMLString(groupsArray);
}
}
})();
2012-09-05
Divisors.
I wrote the code below to check if the results are correct by comparison with a simple brute-force way.
In hand calculation, you have to find an integer that satisfies the condition instead of math.sqrt(i).
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# divisors.py - returns list of divisors
import math, sys, traceback
def check1by1(int_num): # check all numbers from 1 to int_num.
int_num = abs(int_num)
if int_num == 0:
return None
else:
div_list = []
for i in range(1, int_num + 1):
if int_num % i == 0:
div_list.append(i)
return div_list
def getdivisors(int_num): # avoid unnecessary calculation.
"""Return list of divisors of int_num. (None if int_num == 0.)"""
int_num = abs(int_num)
if int_num == 1:
return [1]
elif int_num == 0:
return None
else:
div_list = [1, int_num]
start = 2
step = 1
if int_num % 2 != 0: # if int_num is odd, even divisors are excluded.
start = 3
step = 2
for i in range(start, int(math.sqrt(int_num)) + 1, step):
if int_num % i == 0:
div_list.append(i)
if i != int_num / i:
div_list.append(int_num / i)
return sorted(div_list)
if __name__ == '__main__':
try:
num = int(sys.argv[1])
except IndexError:
print('usage: python divisors.py integer')
sys.exit(0)
simple = check1by1(num)
print('check1by1 ', num, simple)
shortcut = getdivisors(num)
print('getdivisors', num, shortcut)
if simple != shortcut: # Error checking.
print('Error.')
Update, September 7, 11:43 p.m. JST: xrange() instead of range(), benchmark().
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# divisors.py - returns list of divisors
import math, sys, time
def benchmark(int_num, fn):
start_time = time.clock()
result = fn(int_num)
elapsed_time = time.clock() - start_time
return result, elapsed_time
def check1by1(int_num): # check all numbers from 1 to int_num.
int_num = abs(int_num)
if int_num == 0:
return None
else:
div_list = []
for i in xrange(1, int_num + 1):
if int_num % i == 0:
div_list.append(i)
return div_list
def getdivisors(int_num): # avoid unnecessary calculation.
"""Return list of divisors of int_num. (None if int_num == 0.)"""
int_num = abs(int_num)
if int_num == 1:
return [1]
elif int_num == 0:
return None
else:
div_list = [1, int_num]
start = 2
step = 1
if int_num % 2 != 0: # if int_num is odd, even divisors are excluded.
start = 3
step = 2
for i in xrange(start, int(math.sqrt(int_num)) + 1, step):
if int_num % i == 0:
div_list.append(i)
div_result = int_num / i
if i != div_result:
div_list.append(div_result)
return sorted(div_list)
if __name__ == '__main__':
try:
num = int(sys.argv[1])
except IndexError:
print('usage: python divisors.py integer')
sys.exit(0)
simple = benchmark(num, check1by1)
shortcut = benchmark(num, getdivisors)
if simple[0] != shortcut[0]: # Error checking.
print('Error.')
print('check1by1 ', num, simple)
print('getdivisors', num, shortcut)
print('time difference: ' + str(simple[1] - shortcut[1]) + ' sec.')
2012-09-02
Python: Filtering Delicious bookmarks by tags
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# bmfilter.py - Filter bookmarks by tags.
import bmconv
def tagfilter(tags_list):
"""Return a list of bookmark dictionaries."""
return filter(lambda x: set(tags_list) <= set(x['tags']), bmconv.main())
if __name__ == '__main__':
print(tagfilter(['book', 'history']))
The above example outputs only bookmarks that have both 'book' and 'history' tags.Update, September 2, 8:41 p.m. JST: AND/OR filters.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# bmfilter.py - Filter bookmarks by tags.
import bmconv
def andfilter(tags_list):
"""Return a list of bookmarks that have all the tags in tags_list."""
return filter(lambda x: set(tags_list) <= set(x['tags']), bmconv.main())
def orfilter(tags_list):
"""Return a list of bookmarks that have any of the tags in tags_list."""
return filter(lambda x: len(set(tags_list).intersection(set(x['tags']))) > 0, bmconv.main())
if __name__ == '__main__':
# print(andfilter(['book', 'history']))
print(orfilter(['cd', 'dvd']))
Update, September 3, 6:59 p.m. JST: Changed function name and arguments. Added case sensitivity switch.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# bmfilter.py - Filter bookmarks by tags.
import bmconv
def tagfilter(tags_list, bookmarks_list, filter_type_and=True, ignore_case=True):
"""Return a list of dictionaries of bookmarks filtered from bookmarks_list by tags in tags_list."""
def proc_case(str_list):
if ignore_case:
return map(lambda x: x.upper(), str_list)
else: # case sensitive
return str_list
if filter_type_and: # AND
return filter(lambda x: set(proc_case(tags_list)) <= set(proc_case(x['tags'])), bookmarks_list)
else: # OR
return filter(lambda x: len(set(proc_case(tags_list)).intersection(set(proc_case(x['tags'])))) > 0, bookmarks_list)
if __name__ == '__main__':
print(tagfilter(['book', 'history'], bmconv.main()))
## bookmarks that have both tags 'book' and 'history'
## (case insensitive. also matches 'Book', 'History', etc.)
print(tagfilter(['cd', 'dvd'], bmconv.main(), False))
## bookmarks that have any of tags 'cd' and 'dvd'
## (case insensitive. also matches 'CD', 'Cd', 'DVD', 'Dvd', etc.)
print(tagfilter(['Apple'], bmconv.main(), True, False))
## doesn't match 'apple'.
Python: Converting Delicious bookmarks.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# bmconv.py - Read Delicious.com bookmark file and convert it into a list of dictionaries.
import re
bookmark_file = 'delicious.html'
def main():
"""Return a list of dictionaries of bookmarks."""
lines_list = []
with open(bookmark_file, 'r') as f:
lines_list = f.readlines()
entries_list = []
for idx, line in enumerate(lines_list):
entry = {}
if re.match(r'^<DT>', line):
entry['url'] = re.match(r'^.*HREF=\"([^\"]+)\"', line).group(1)
entry['add_date'] = re.match(r'^.*ADD_DATE=\"([^\"]+)\"', line).group(1)
entry['private'] = re.match(r'^.*PRIVATE=\"([^\"]*)\"', line).group(1)
entry['tags'] = re.match(r'^.*TAGS=\"([^\"]*)\"', line).group(1).split(',')
entry['title'] = re.match(r'^.*<A [^>]+>(.*)</A>', line).group(1)
if re.match(r'^<DD>', lines_list[idx + 1]):
dd_tmp = []
increment = 1
try:
while True:
if re.match(r'^<DT>', lines_list[idx + increment]):
break
dd_tmp.append(re.match(r'^(<DD>)?(.*)$', lines_list[idx + increment]).group(2))
increment += 1
except:
pass
entry['description'] = '\n'.join(dd_tmp)
entries_list.append(entry)
return entries_list
if __name__ == '__main__':
print(main())
Download bmconv.py from Google Drive
2012-08-26
Using PyRSS2Gen in time zones other than GMT
--- PyRSS2Gen.py.orig 2012-08-25 10:22:14.292968887 +0000
+++ PyRSS2Gen.py 2012-08-25 13:38:58.838836110 +0000
@@ -57,12 +57,13 @@
# Isn't there a standard way to do this for Python? The
# rfc822 and email.Utils modules assume a timestamp. The
# following is based on the rfc822 module.
- return "%s, %02d %s %04d %02d:%02d:%02d GMT" % (
+ return ("%s, %02d %s %04d %02d:%02d:%02d %s" % (
["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()],
dt.day,
["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][dt.month-1],
- dt.year, dt.hour, dt.minute, dt.second)
+ dt.year, dt.hour, dt.minute, dt.second,
+ dt.strftime('%z'))).strip()
##
Update, August 28, 2:07 p.m. JST: Output timezone in any case ('GMT' by default).
--- PyRSS2Gen.py.orig 2012-08-25 10:22:14.292968887 +0000
+++ PyRSS2Gen.py 2012-08-28 04:31:25.535324750 +0000
@@ -57,12 +57,15 @@
# Isn't there a standard way to do this for Python? The
# rfc822 and email.Utils modules assume a timestamp. The
# following is based on the rfc822 module.
- return "%s, %02d %s %04d %02d:%02d:%02d GMT" % (
+ tz = 'GMT' # default timezone
+ if dt.tzinfo:
+ tz = dt.strftime('%z')
+ return "%s, %02d %s %04d %02d:%02d:%02d %s" % (
["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()],
dt.day,
["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][dt.month-1],
- dt.year, dt.hour, dt.minute, dt.second)
+ dt.year, dt.hour, dt.minute, dt.second, tz)
##
Update, September 1, 5:06 p.m. JST: Simplified the patch.
--- PyRSS2Gen.py.orig 2012-08-25 10:22:14.292968887 +0000
+++ PyRSS2Gen.py 2012-09-01 07:16:36.291449545 +0000
@@ -57,12 +57,13 @@
# Isn't there a standard way to do this for Python? The
# rfc822 and email.Utils modules assume a timestamp. The
# following is based on the rfc822 module.
- return "%s, %02d %s %04d %02d:%02d:%02d GMT" % (
+ return "%s, %02d %s %04d %02d:%02d:%02d %s" % (
["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()],
dt.day,
["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][dt.month-1],
- dt.year, dt.hour, dt.minute, dt.second)
+ dt.year, dt.hour, dt.minute, dt.second,
+ dt.strftime('%z') if dt.tzinfo else 'GMT') # default timezone is 'GMT'
##
2012-08-05
Making ruby refe output without garble on UTF-8 terminal
#!/bin/sh
cd "`dirname "$0"`"
exec ruby -Ke -I bitclust/lib bitclust/bin/refe -d db-1_9_3 -e w "$@"
2012-01-03
Patch for test_commands.py in Python 2.5.6
Environment:
- CentOS 6.2 x86_64 on VMware
- Python 2.5.6
Symptom:
- make test fails.
Solution:
- Apply the patch available here on this issue or the following (patch on my Google Docs) to Lib/test/test_commands.py.
--- Lib/test/test_commands.py.orig 2006-06-29 04:10:08.000000000 +0000
+++ Lib/test/test_commands.py 2012-01-02 11:19:28.535171924 +0000
@@ -46,11 +46,7 @@
# drwxr-xr-x 15 Joe User My Group 4096 Aug 12 12:50 /
# Note that the first case above has a space in the group name
# while the second one has a space in both names.
- pat = r'''d......... # It is a directory.
- \+? # It may have ACLs.
- \s+\d+ # It has some number of links.
- [^/]* # Skip user, group, size, and date.
- /\. # and end with the name of the file.
+ pat = r'''^.*(\/\.)[\ ]*[\n\r]*$
'''
self.assert_(re.match(pat, getstatus("/."), re.VERBOSE))
Tips for building Python 2.5.6 with SSL on CentOS 6.2 (x86_64)
- Modules/Setup.dist (Python 2.5.6)
- setup.py (ssl package)
--- Modules/Setup.dist.orig 2006-08-06 07:26:21.000000000 +0000
+++ Modules/Setup.dist 2012-01-02 16:09:27.904863909 +0000
@@ -203,10 +203,10 @@
# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
-#SSL=/usr/local/ssl
-#_ssl _ssl.c \
-# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
-# -L$(SSL)/lib -lssl -lcrypto
+SSL=/usr
+_ssl _ssl.c \
+ -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
+ -L$(SSL)/lib64 -lssl -lcrypto
# The crypt module is now disabled by default because it breaks builds
# on many systems (where -lcrypt is needed), e.g. Linux (I believe).
Then build Python 2.5.6 as usual.
Next, you may need ssl package from pypi.
Edit setup.py as follows (patch file on Google Docs page):
--- setup.py.orig 2009-07-28 00:45:12.000000000 +0000
+++ setup.py 2012-01-02 16:40:09.447439694 +0000
@@ -130,7 +130,8 @@
ssl_incs += krb5_h
ssl_libs = find_library_file(compiler, 'ssl',
- ['/usr/lib'],
+ ['/usr/lib',
+ '/usr/lib64'],
['/usr/local/lib',
'/usr/local/ssl/lib',
'/usr/contrib/ssl/lib/'
Then, build the package with make.
cf. Getting SSL Support in Python 2.5.1
2011-09-19
R brush for SyntaxHighlighter
I'm working on a custom brush to extend SyntaxHighlighter to support the syntax of R.
The project is on GitHub.
The brush file is SyntaxHighlighter/scripts/shBrushR.js.
Here's an example.
resultframe <- sessionframe <- temp <- bpdata[1,]
transform(resultframe, morningbedtime=c(0))
resultframe <- resultframe[0,]
for (i in 2:length(bpdata$ID)) {
tempnext <- bpdata[i,]
if ((abs(difftime(temp$datetime, tempnext$datetime, units="mins")) > 10) || (i == length(bpdata$ID))) {
if (i == length(bpdata$ID)) {
sessionframe <- merge(sessionframe, tempnext, all=T)
sessiondatetime <- strptime(tempnext$datetime, "%Y-%m-%d %H:%M:%S")
} else {
sessiondatetime <- strptime(temp$datetime, "%Y-%m-%d %H:%M:%S")
}
sessionmax <- mean(sessionframe$max)
sessionmin <- mean(sessionframe$min)
sessionbpm <- mean(sessionframe$bpm)
if ((morningbegin <= sessiondatetime$hour) && (sessiondatetime$hour < morningend)) {
sessionmorningbedtime <- c(0)
} else {
sessionmorningbedtime <- c(1)
}
resultframe <- merge(resultframe, data.frame(datetime=sessiondatetime, max=sessionmax, min=sessionmin, bpm=sessionbpm, morningbedtime=sessionmorningbedtime), all=T)
sessionframe <- temp <- tempnext
} else {
sessionframe <- merge(sessionframe, tempnext, all=T)
temp <- tempnext
}
}
2011-08-09
Default settings for bar/column chart axes in major spreadsheet applications may lead to chart junk.
Depending on data, Excel, OpenOffice.org Calc, Google Docs spreadsheet, which are the most popular spreadsheet applications, scale chart axes differently by default.
Below are examples. (twitpic.com)
Note that the vertical axes start from 0, 75, 80 depending on the values in the charts in Excel and OpenOffice.org Calc. Google Docs' chart has its vertical axis from 80, not zero.
The problem is that the mysterious feature may lead to chart junk because the axes don't start from zero and are misleading.
I couldn't find how to fix this by changing default settings with these applications.
So I'm working on Excel macro which scans all the bar/column charts in the current book and make their axes start from zero.
You can download Excel macro book file (FixChartAxes.xlsm) and Excel addin file (FixChartAxes.xlam). (both from Google Docs)
You can see the source code of the macro at Gist.
I think the best solution is that Microsoft fixes this problem, because it is the most influential company in the spreadsheet software industry.
To Microsoft: Please make the default settings of bar/column chart axes start from zero by default.
2011-07-02
R memo: elements' positions in vector under conditions
> x <- c(10,20,30) > x [1] 10 20 30If you want to get positions of the elements in vector x which meet a condition, for example, x > 10, you can do like this:
> (1:length(x))[x > 10] [1] 2 3The second and third elements meet the condition.
The first part,
> (1:length(x)) [1] 1 2 3gives you a vector which counts from 1 up to the number of the elements in x.
The last part,
> x > 10 [1] FALSE TRUE TRUEgives you a vector which shows if each element meets the condition (greater than 10).
Then, you can get only the elements which correspond to TRUE by
> (1:length(x))[x > 10]
c.f. 13. ベクトル要素へのアクセス
2011-05-07
MathML test
This post is for testing MathJax on Blogger.
The above examples are generated by Microsoft Mathematics.
The following is from MathML Samples.
The following is generated by formulator-mathml.


