裏 RjpWiki

文字通り,RjpWiki の裏を行きます
R プログラム コンピュータ・サイエンス 統計学

次の 13 日の金曜日はいつか?

2020年12月29日 | Python

ツェラーの公式を利用して列挙する

def Zeller(y, m, d):
    w = ['Sat', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri']
    if m == 1 or m ==2:
        m += 12
        y -= 1
    C = y // 100
    Y = y % 100
    return w[(d + 26*(m+1)//10 + Y + Y//4 -2*C + C // 4) % 7]

for y in range(2021, 2030):
    for m in range(1, 13):
        if Zeller(y, m, 13) == 'Fri':
            print(y, m)

2021 8
2022 5
2023 1
2023 10
2024 9
2024 12
2025 6
2026 2
2026 3
2026 11
2027 8
2028 10
2029 4
2029 7

コメント

pandas version 1.0.0 (Python)

2020年12月28日 | Python

データフレームのマークダウン出力ができるようになった

>>> pd.__version__
'1.0.1'
>>> df = pd.DataFrame({"a": list("abcde"), "b": [1,2,3,4,5]})
>>> df
   a  b
0  a  1
1  b  2
2  c  3
3  d  4
4  e  5
>>> df.to_markdown()
'|    | a   |   b |\n|---:|:----|----:|\n|  0 | a   |   1 |\n|  1 | b   |   2 |\n|  2 | c   |   3 |\n|  3 | d   |   4 |\n|  4 | e   |   5 |'
>>> print(df.to_markdown())
|    | a   |   b |
|---:|:----|----:|
|  0 | a   |   1 |
|  1 | b   |   2 |
|  2 | c   |   3 |
|  3 | d   |   4 |
|  4 | e   |   5 |

コメント

groupby で,自作の関数を適用する(Python)

2020年12月27日 | Python

df2 = df.groupby(群)

df2.agg(自作関数の名前)

コメント

Python だからって...,numpy も使えば?

2020年12月26日 | Python

文字列中に,どのような文字が幾つあったか知りたいって...

>>> import numpy as np
>>> str = 'あいうえおあおaiueoao999112'
>>> index, count = np.unique(list(str), return_counts=True)
>>> index
array(['1', '2', '9', 'a', 'e', 'i', 'o', 'u', 'あ', 'い', 'う', 'え', 'お'],
      dtype='<U1')
>>> count
array([2, 1, 3, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2])
>>> 
>>> list(index)
['1', '2', '9', 'a', 'e', 'i', 'o', 'u', 'あ', 'い', 'う', 'え', 'お']
>>> list(count)
[2, 1, 3, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2]

コメント

さて,ここで問題です Challenge0001 (Python)

2020年12月25日 | Python

a, b, c, d の4個の数字を入力とする

もしどれかが 0 なら,それぞれに 0.5 を加える

x = a * d / (b * c)

としたとき,x か  1 / x の大きい方を返す関数を定義せよ

言語は問わない。合計文字数が少ない方がいいぞ!

 

解答例は,ずっとスクロールダウンして...

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

import numpy as np

def func(a, b, c, d):
  if a * b * c * d == 0:
  a, b, c, d = np.array([a, b, c, d])+0.5
  OR = a * d / (b * c)
  return max(OR, 1 / OR)

func(1,2,3,4) # 1.5
func(0,2,3,4) # 3.8888888888888893

コメント

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

コメント

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 倍も違う。

コメント

リスト要素の複数削除(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

コメント

微少量 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

... 同じだ

 

コメント

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

コメント

別名で参照(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])

コメント

前の記事の展開(Python)

2020年12月18日 | Python

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

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

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

コメント

式の右辺の if - else (Python)

2020年12月18日 | Python

Python だと

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

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

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

コメント

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

2020年12月17日 | Python

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

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

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

 

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

 

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

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

コメント

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))

コメント