pythonでExcelからTSVに変換してみた。
DataFrameでもできるのだけども、ストリーム系でないとメモリをめっちゃ食ってしまう。 ソース 37万件のデータで実施した場合、 ■今回のソースの場合 $ time python excel2tsv_e.py KEN_ALL.xlsx > ken_all2.txt real 0m38.720s user 0m38.614s sys 0m0.105s ■DataFrameを使った場合 $ time python excel2tsv_p.py KEN_ALL.xlsx real 0m47.467s user 0m47.094s sys 0m1.139s lxml速い。 startイベントでendイベントの関数を生成するの結構良いかも。 あと、4階層以下は都度都度メモリ解放しなくしてるのもうまく働いている。 DataFrameだと最大800Mまでメモリを使用するが、今回のだと50Mくらい。 for event, elem in parser.read_events(): if event == "end": yield event, elem, stack stack.pop() if 1 <= len(stack) <= 2: stack[-1].remove(elem) level -= 1 else: level += 1 stack.append(elem) yield event, elem, stack PR |
javaでflatMapを覚えてから奇妙だなと思っていた。
これって何に使うのだろうかと。 結論から言うと直積を求めたいときに使うのである。 もし、組み合わせを求めたい場合、どのように求めるだろうか。 ■pythonソース teams = range(5) [(x, y) for xi, x in enumerate(teams) for yi, y in enumerate(teams) if xi < yi]■python結果 [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] 実はこれと同じことをflatMapでも行える。 ■javascriptソース range = (x)=>function*(){ for(var i = 0;i<x;i++) {yield i;}}; teams = range(5); Array.from([[]]) .flatMap(x=>Array.from(teams()).map(y=>x.concat(y))) .flatMap((x, xi)=>Array.from(teams()).filter((y,yi)=>xi<yi).map(y=>x.concat(y)))■javascript結果 (10) [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)] 0: (2) [0, 1] 1: (2) [0, 2] 2: (2) [0, 3] 3: (2) [0, 4] 4: (2) [1, 2] 5: (2) [1, 3] 6: (2) [1, 4] 7: (2) [2, 3] 8: (2) [2, 4] 9: (2) [3, 4] length: 10 __proto__: Array(0)おもしろいなあ。 |
Pythonでの不満。Python2にあったsorted関数のcmpがなくなって、keyになった。
なぜ、cmpはなくなったのだろうか?考えてみた。 まず、sortedへの不満として、複数キーの昇順・降順ができなくなった。というものがあった。 誤りである。 どうやらkeyにタプルを返すと勝手に複数キーの昇順としてソートしてくれるようだ。 つまり、文字は反転。数字はマイナスにすることで、それらしきものができる。 c=[('a', 1), ('a', 2), ('b', 2), ('b', 1)] sorted(c, key=lambda x: (tuple(map(lambda z:(0xff-z), x[0].encode("cp932"))), -x[1])) [('b', 2), ('b', 1), ('a', 2), ('a', 1)]ここで気づいた。この比較用キーの作成はcmpの場合、ソート方法に依存してしまう。O(2*NlogN)の頻度で比較用キーが作成されてしまうのだ。 この点、key指定だと比較用キーはO(N)のみの作成となる。 すばらしい ただし、文字列の降順としては可変長の場合、前述の方法は使えない。なので、classを作ってみた。 class Keys: def __init__(self, v, isAscs): self.v = v self.isAscs = tuple(isAscs) def __lt__(self, other): for i, s, isAsc, o in zip(range(len(self.isAscs)-1, -1, -1), self.v, self.isAscs, other.v): lt = [lambda p1, p2: p1 > p2, lambda p1, p2: p1 < p2][isAsc] ret = lt(s, o) if ret or i and lt(o, s): break return ret @staticmethod def of(isAscs, keymap=lambda x:x): return lambda item: Keys(keymap(item), isAscs) if __name__ == "__main__": arr = [("a", 2), ("b", 1), ("a", 1), ("b", 2)] print(arr) #1項目め降順、2項目め昇順 print(sorted(arr, key=Keys.of((False, True)))) #1項目め2文字目昇順、1項目め1文字目昇順 print(sorted(arr, key=Keys.of((True, False), keymap=lambda x:(x[0][1], x[0][0]))))うん、素晴らしい。 |
Pythonでフィールドを定義するときに他言語と合わせて クラスブロックに入れてみた場合とコンストラクタに入れてみた場合を比較してみた。 i = 0 def func(): global i i = i + 1 return i class Person: vals1 = func() #field define def __init__(self): print '[Person.__init__]' self.vals2 = func() #costruct print "finished compile." func() info = Person() print info.vals1, info.vals2 del info info = Person() print info.vals1, info.vals2結果 finished compile. [Person.__init__] 1 3 [Person.__init__] 1 4 どうやらクラスブロックにフィールドを指定したら、コンパイル時に プリプロセスされてしまってスカラーに変換されてるっぽい。 |
Pythonの変数のスコープについてなぜグローバル変数を用いるためにglobalをつける必要があるか考察してみた。 まず、C言語の関数から見てみよう int func() { int L; L = 23; printf("%d%s", L, G); //出力:"23bit" } C言語において、変数は「Use with definition」である。 次に、VBの関数を見てみよう。 Sub func L = 23 print L & G ’出力:"23bit" End Sub VBにおいて、Option Explicitをつけない場合、変数は「Use without definition」である。 いよいよPythonの関数を見てみよう def func(): L = 23 print L,G #出力:"23bit" Pythonにおいて、変数は「Use with definition. But writing is definition.」である。 実際に変数Gには何が設定されているのか知りたければGで検索すれば設定場所がひっかかる。 def func2(): global G G = "bit" global変数に値を設定する場合、ローカル変数の「値を設定して使う」というルールに参加させるため、globalキーワードを用いる。 なぜ、こんな仕様になったのか考えてみると、システム屋ではない人が作ってもPythonは整った文になるように設計されているということである。 さらに次のルールが生まれる。 とてもよく考えられているルールではないだろうか? |
| ホーム |
忍者ブログ [PR] |