裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

np.nan == np.nan は? (Python)

2020年12月24日 | Python

import numpy as np
print(np.nan == np.nan)
print(np.nan != np.nan)

の結果がどうなるか答えよ

 

答えは,スクロールした,ずーーーと下の方にある

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

print(np.nan == np.nan) は False
print(np.nan != np.nan) は True

正しくは is, is not を使うべきなのだ

print(np.nan is np.nan) は True
print(np.nan is not np.nan) は False

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

range() と numpy.range() -- Python

2020年12月23日 | Python

range と numpy.arange は速度が大違い。numpy.range を使うべし。

import numpy as np

def Eratosthenes(n):
    """ n 以下の素数をエラトステネスの篩で生成 """
    tbl = np.arange(n+1, dtype=int)
    tbl[1] = 0
    for i in range(2, int( np.sqrt(n))+1):
        if tbl[i]:
            tbl[range(2*i, n+1, i)] = 0
    return tbl[tbl > 0]

def Eratosthenes2(n):
    """ n 以下の素数をエラトステネスの篩で生成 """
    tbl = np.arange(n+1, dtype=int)
    tbl[1] = 0
    for i in range(2, int(np.sqrt(n))+1):
        if tbl[i]:
            tbl[np.arange(2*i, n+1, i)] = 0
    return tbl[tbl > 0]

from time import time as t
s = t();a = Eratosthenes(10000000);print(t()-s) # 4.958sec
s = t();b = Eratosthenes2(10000000);print(t()-s) # 0.268sec

な,な,なんと!18 倍も違う。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

リスト要素の複数削除(Python)

2020年12月22日 | Python

リストから k 番目の要素を削除したものを返す。k はリストで指示する(要素が 1 個の場合もリストで指示)
hoge = ["a", "b", "c", "d"] のとき
rdel(hoge, [2]) は ['a', 'b', 'd'] を返す
rdel(hoge, [1, 3]) は ['a', 'c'] を返す

def rdel(lis, ind):
    lis2 = lis.copy()
    [lis2.pop(int(i)) for i in sorted(ind)[::-1]]
    return lis2

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

微少量 epsilon (Python)

2020年12月21日 | Python

R の .Machine$double.eps

the smallest positive floating-point number x such that 1 + x != 1. It equals double.base ^ ulp.digits if either double.base is 2 or double.rounding is 0; otherwise, it is (double.base ^ double.ulp.digits) / 2. Normally 2.220446e-16.

> options(digits=16)
> .Machine$double.eps
[1] 2.220446049250313e-16

> 2^-52
[1] 2.220446049250313e-16

Python では,

>>> import sys
>>> sys.float_info.epsilon
2.220446049250313e-16

... 同じだ

追記 2021/05/19

Julia だと,

julia> eps()
2.220446049250313e-16

julia> 2^-52
2.220446049250313e-16

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Python 3 で,ベクトル・配列の代入演算

2020年12月20日 | Python

Python 3 において,

import numpy as np
a = np.array([[1,2,3], [4,5,6], [7,8,9]])
a[1, :] += 3
a[1, :] -= 3
a[1, :] *= 3

は問題ないが,

a[1, :] /= 3

はエラーを生じる

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
in
----> 1 a[1, :] /= 3

TypeError: No loop matching the specified signature and casting
was found for ufunc true_divide

ベクトルの場合も同じ。

b = np.array([1, 3, 7])
b += 10
b -= 10
b *= 10

は問題ないが,

b /= 10

はエラーを生じる

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
in
----> 1 b /= 10

TypeError: No loop matching the specified signature and casting
was found for ufunc true_divide

a /= 3 は a = np.true_divide(a, 3) とは違うということが問題の本質。

それはさておき

これを回避するには,np.array()  で dtype=float を指定する

a = np.array([[1,2,3], [4,5,6], [7,8,9]], dtype=float)
a[1, :] /= 3
a
b = np.array([1, 3, 7], dtype=float)
b /= 10
b

または,dtype=float となるように,少なくとも一つの数値を小数点付きで指定する

a = np.array([[1.0,2,3], [4,5,6], [7,8,9]])
a[1, :] /= 3
a

b = np.array([1.0, 3, 7])
b /= 10
b

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

別名で参照(Python)

2020年12月19日 | Python

Python では,ベクトルや配列を別の変数に代入しても,新しいメモリが確保されるのではなくもとのメモリが参照される。これはときどきやっかいなバグのもとになるが,便利に使うこともできる。

>>> import scipy as sp
>>> a = sp.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

b, c に a の一部を代入する。

>>> b = a[:6]
>>> c = a[6:]
>>> b
array([0, 1, 2, 3, 4, 5])
>>> c
array([6, 7, 8, 9])

元の a を変化させると

>>> a *= 2
>>> a
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

b, c も変化する。b, c は別のメモリ上にあるのではなく,元の a の部分を指しているから当たり前。

>>> b
array([ 0,  2,  4,  6,  8, 10])
>>> c
array([12, 14, 16, 18])

b, c の要素を変化させると a も変わる

>>> c[2] = 200
>>> c
array([ 12,  14, 200,  18])
>>> a
array([  0,   2,   4,   6,   8,  10,  12,  14, 200,  18])

しかし,以下のようにして c 全体を置き換えると,新たに c 用にメモリが確保されるようで,c は変わるが,a は不変だ。これも,使い方を間違えるとバグの元になるようだ。

>>> c = sp.repeat(20, 4)
>>> c
array([20, 20, 20, 20])
>>> a
array([  0,   2,   4,   6,   8,  10,  12,  14, 200,  18])

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

前の記事の展開(Python)

2020年12月18日 | Python

a = ("foo", "bar", "baz")

のとき,x が "foo" なら 5,"bar" なら 9,"baz" なら 17 を返すようにするなら(他の値はないとする)

(5, 9, 17)[("foo", "bar", "baz").index(x)]

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

式の右辺の if - else (Python)

2020年12月18日 | Python

Python だと

x = "odd" if a%2 == 1 else "even"

になるんだけど,以下の方がまだましだと思うのだ

x = ("odd", "even")[a%2 != 1]

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

自作パッケージの探索径路(サーチパスともいう)の設定法

2020年12月17日 | Python

環境変数にサーチパスを付け加える例としては,先頭に付け加える例が説明されることが多いようにみえる。

もう一つの方法,import sys; sys.path.append("foo") では,当然ながら末尾に付け加える例が説明されることが多いようにみえる。

当然ながら,後者を前者と同じにするためには,import sys; sys.path.insert(0, "foo") としなければならない。

 

というのに,しばしはまってしまって,まったりとした時間をすごしてしまった。

 

結論としては,自作パッケージにより,既存の何らかのものが覆い隠されてしまわないように,サーチパスの末端に append するほうがよいだろうということ。

自作パッケージより前に探索されてしまうものがあるなら,自作パッケージの名前を変えましょう。それが無難というもの。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Python 嫌いだけど,こんな Python プログラムはいやだ(その7)

2020年12月16日 | Python

きりがないので,これで止める。

R でもそうだけど,for を使ったところは,使わないように書き換えるのが吉。

単に行数が短くなると言うことではなく,その方が効率的だから。

Java や JavaScript, C, C++ 古くは FORTRAN などの経験者はどうしても自分の経験から for ループを使ったコードを,「安易に」書いてしまう。

R や Python はそれを実現する,1つの関数を持っている。それを使うべし。

for を多用している Python プログラムは,「参考にしてはならない!!」

旧人類の真似をしてるうちは,新人類にはなれませんっ!

ベテランは,自己の経験に基づくのではなく,Python ではどのように書くのが「普通か」ということを探索すべし。自分ほど経験豊富なプログラマ(エッヘン)は何でもプログラムできるからと言って,旧来の for ループでなんでもかんでも書くというのは,止めるべし。

import math
data = [66, 59, 62, 64, 63,
        68, 65, 59, 68, 64,
        65, 51, 67, 64, 83,
        59, 61, 62, 57, 72,
        65, 64, 54, 60, 53,
        65, 67, 60, 53, 79,
        74, 53, 61, 68, 75,
        50, 57, 55, 66, 56,
        55, 61, 70, 71, 49,
        69, 70, 80, 73, 72]

n = len(data)       #   The number of scores
print("n = %d" % n)

# print("Data...")
# i = 1
# for x in data:
#     print("%5d:"%i + "  %f"%x)
#     i+=1

# sum = 0.0
# for x in data:
#    sum += x
# mean = sum / n
mean = sum(data) / n
print("Mean = %g" % mean)
#ssum = 0.0
#for x in data:
#    ssum += sqr(x - mean)
# var = ssum / n
var = sum((x - mean)**2 for x in data) / n
sd = math.sqrt(var)
# print("Variance = %f"%var + "     sd = %f"%sd)
print("Variance = %g     sd = %g" % (var, sd))
# uvar = ssum / (n - 1.0)
uvar = var * n / (n - 1)
sd_uvar = math.sqrt(uvar)
# print("Unbiased Var. = %f"%uvar + "     sd(uvar) = %f"%sd_uvar)
print("Unbiased Var. = %g     sd(uvar) = %g" % (uvar, sd_uvar))

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Python 嫌いだけど,こんな Python プログラムはいやだ(その6)

2020年12月15日 | Python

d = 'a b c d e'

s = d.split()
label = []
for v in s:
    label.append(v)

というようなことをやっているが,作られる label は s と同じだ。つまり,3 行使って無駄なことをしている。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Python 嫌いだけど,こんな Python プログラムはいやだ(その5)

2020年12月14日 | Python

for 文を使って書かれると,何をやっているのか,一目で分からない

以下のプログラム,何やっているかすぐ分かる?scale は何になる?

scale = 0.0
for t in range(n_dim):
    for i in range(n_row):
        if scale < abs(y[t][i]):
            scale = abs(y[t][i])
    for j in range(n_col):
        if scale < abs(x[t][j]):
            scale = abs(x[t][j])

以下と同じ

mx = max(abs(np.ravel(x)))
my = max(abs(np.ravel(y)))
scale = max(mx, my)

一行で書いてもいいけど

scale = max(abs(np.hstack((np.ravel(x), np.ravel(y)))))

つまりね,x, y の絶対値をとったものの最大値

scale = max(np.amax(abs(x)), np.amax(abs(y)))

と書いても同じ。(max と np.amax とが使われていて,Python のいやらしさが出ているけど)

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Python 嫌いだけど,こんな Python プログラムはいやだ(その4)

2020年12月13日 | Python

例えば

n_col = 5
a = [1, 2, 3, 4, 5]

という前提で

b = np.zeros((n_col, n_col))
for j in range(n_col):
    b[j, j] = 1.0 / (a[j] ** 0.5)

なにやってんの?

a[j] ** 0.5 は a が(例によって)リストで,a[j] はint か float なのだろうから仕方ないが numpy.sqrt(a[j]) と指定したいところだろう。

b = np.diag(1/np.sqrt(a))

の一行ですむところ。何をやろうとしているか,一目でわかる。
np.zeros を知っているのに,np.diag を知らないとは???

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Python 嫌いだけど,こんな Python プログラムはいやだ(その3)

2020年12月12日 | Python

っていうか,これ,Python のプログラムじゃないよね...って,話
でも,まあ,書いてみよう

行きがかり上,A は 二次元配列ではなく,二重リストだ(何度でも言うが,なんでリストなんだ?)。n_col, n_row はまあ,わかる。

fc = []
for j in range(n_col):
    sum = 0
    for i in range(n_row):
        sum += A[i][j]
    fc.append(sum)

何をやっているのかこれだけ見たらわかるかも知れないが,注意深く見ないとわからない。行和か??列和か??

やってみれば分かるけど,列和だ!!

A を numpy.ndarray にすれば,

import numpy as np
fc = np.array(A).sum(axis=0)

と一発で,何をやっているかも一目で分かる(n_col や n_row も,少なくともここでは,必要ないしね)。fc は nupy.ndarray。

作者は,よほどリストがお好きなようだ。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Python 嫌いだけど,こんな Python プログラムはいやだ(その2)

2020年12月11日 | Python

以下のようなデータを読むのに数十行費やしているプログラムがある。

======= begin
いろいろ注釈もあるんだろう

/   row     column
    2      3
c1  c2  c3
r1  1  5  2
r2  3  2  6
======= end

行名や列名も取り出したいということなんだけど以下の 4 行で済むし,行数列数もデータファイル中に書く必要はない(人間が数えて書くとエラーが生じる可能性すらある)。pd.read_csv にここに書いた以外にたくさんの引数があるのを把握している人も少ないかも知れない(大概のことは引数の指定でできるはずなので,help をチェックすべし)

import pandas as pd

dat = pd.read_csv("dummy.txt", delim_whitespace=True, skiprows=4)
columns = dat.columns
index = dat.index

pandas のデータフレームで不都合なら,numpy.array(dat) とすればよいだけ。

データ入力のようなよくある処理に,独自のプログラムを書くのは無駄な作業だ。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村