【Python】Pandasのmergeとconcat

Pandas の pd.mergepd.concat の使い方の備忘録。

merge


2つのデータフレームを結合する。横結合(join)に対応。

SQLで使われる内部結合(inner join)、外部結合(outer join)、左結合(left join)、右結合(right join)と同じ機能を一通り扱える。

コード例

pd.merge(df1, df2, how="inner", on="USUBJID")


引数(一部)

引数 内容
how = "inner" で内部結合。
"outer" で外部結合。
"left" で左結合。
"right" で右結合。
on =
left_on =
right_on =
left_index =
right_index =
別表参照。
sort = ソートの有無。Trueでソートする。デフォルトはFalse。
suffixes = 同一列名があった場合、列名末尾に追加する文字を指定。
デフォルトは ('_x' '_y') 。
末尾を_A, _Bとしたければ suffixes = ('_A' '_B') とする。


結合キーの組み合わせ

引数 内容
on = "カラム名" 同名のカラムで結合。
left_on = "カラム名1"
,right_on = "カラム名2"
カラム名をそれぞれ指定して結合。
left_index = True
,right_index = True
インデックス同士で結合。
left_on = "カラム名1"
,right_index = True
左はカラム名、右はインデックスを指定して結合。
left_index = True
,right_on = "カラム名2"
右はカラム名、左はインデックスを指定して結合。


結合方法の組み合わせの例

ADS11 = pd.DataFrame({"ID1":[1,2,3,4,5], "AVAL":[3,5,3,5,6]})
ADS12 = pd.DataFrame({"ID1":[3,4,5,6,7], "ID2":[5,6,7,8,9], "AVAL":[7,8,5,8,7]})
 
#-- ID1で結合。
pd.merge(ADS11, ADS12, how="inner", on="ID1", suffixes=("_11","_12"))
Out[1]: 
   ID1  AVAL_11  ID2  AVAL_12
0    3        3    5        7
1    4        5    6        8
2    5        6    7        5
 
#-- ADS11はID1、ADS12はID2で結合。
pd.merge(ADS11, ADS12, how="inner", left_on="ID1", right_on="ID2")
Out[2]: 
   ID1_x  AVAL_x  ID1_y  ID2  AVAL_y
0      5       6      3    5       7
 
#-- インデックス同士で結合
pd.merge(ADS11, ADS12, how="inner", left_index=True, right_index=True)
Out[36]: 
   ID1_x  AVAL_x  ID1_y  ID2  AVAL_y
0      1       3      3    5       7
1      2       5      4    6       8
2      3       3      5    7       5
3      4       5      6    8       8
4      5       6      7    9       7
 
#-- ADS11はインデックス、ADS12はID1を使って結合
pd.merge(ADS11, ADS12, how="inner", left_index=True, right_on="ID1")
Out[3]: 
   ID1  ID1_x  AVAL_x  ID1_y  ID2  AVAL_y
0    3      4       5      3    5       7
1    4      5       6      4    6       8
 
#-- ADS11はID1、ADS12はインデックスを使って結合
pd.merge(ADS11, ADS12, how="inner", left_on="ID1", right_index=True)
Out[4]: 
   ID1  ID1_x  AVAL_x  ID1_y  ID2  AVAL_y
0    1      1       3      4    6       8
1    2      2       5      5    7       5
2    3      3       3      6    8       8
3    4      4       5      7    9       7


concat


2つ以上のデータフレームを結合する。横結合(join)と縦結合(union)の両機能が扱える。

横結合(join)においては、pd.merge と異なり、3つ以上のデータフレームも一度に扱える特徴を持つ。 一方、結合方式は内部結合(inner join)と外部結合(outer join)の2択になるため、一長一短。使い分けになる。

コード例

pd.concat([df1, df2], axis=0, join="outer", keys=["Group1", "Group2"])
pd.concat([df1, df2, df3], axis=0, join="outer", keys=["Group1", "Group2"])


引数(一部)

引数 内容
axis = 0 で縦結合、1 で横結合。
join = "outer" で全ての列/行を結合。
"inner" で共通する列/行のみ結合。
ignore_index = Trueでインデックスを振りなおす。
デフォルトは False で、結合前のインデックスをそのまま使う。
keys = リスト型でマルチインデックス内のキー名を指定する。
例:["Group1", "Group2"]
※マルチインデックスの設定例を参照。
names = リスト型でインデックス名を指定する。
例:["index1", "index2"]
※マルチインデックスの設定例を参照。
sort = ソートの有無。Trueでソートする。デフォルトはFalse。


結合方法の組み合わせの例

ADS11 = pd.DataFrame({"COL1":[1,3], "AVAL":[3,5]}, index=[1,2])
ADS12 = pd.DataFrame({"COL2":[3,5], "AVAL":[7,8]}, index=[3,2])
 
#-- 縦結合。全ての列を結合。
pd.concat([ADS11, ADS12], axis=0, join="outer")
Out[1]: 
   COL1  AVAL  COL2
1   1.0     3   NaN
2   3.0     5   NaN
3   NaN     7   3.0
2   NaN     8   5.0
 
#-- 縦結合。共通列のみ結合。
pd.concat([ADS11, ADS12], axis=0, join="inner")
Out[2]: 
   AVAL
1     3
2     5
3     7
2     8
 
#-- 横結合。全ての列を結合。
pd.concat([ADS11, ADS12], axis=1, join="outer")
Out[3]: 
   COL1  AVAL  COL2  AVAL
1   1.0   3.0   NaN   NaN
2   3.0   5.0   5.0   8.0
3   NaN   NaN   3.0   7.0
 
#-- 横結合。共通列のみ結合。
pd.concat([ADS11, ADS12], axis=1, join="inner")
Out[4]: 
   COL1  AVAL  COL2  AVAL
2     3     5     5     8


マルチインデックスの設定例

#-- 縦結合
pd.concat([ADS11, ADS12]
            ,axis = 0, join = "outer"
            ,keys = ["Group1", "Group2"]
            ,names = ["Index1","Index2"]
            ,sort   = True
    )
 
Out[1]: 
               AVAL  COL1  COL2
Index1 Index2                  
Group1 1          3   1.0   NaN
       2          5   3.0   NaN
Group2 3          7   NaN   3.0
       2          8   NaN   5.0
 
#-- 横結合
pd.concat([ADS11, ADS12]
            ,axis = 1, join = "outer"
            ,keys = ["Group1", "Group2"]
            ,names = ["Index1","Index2"]
            ,sort   = True
    )
 
Out[2]: 
Index1 Group1      Group2     
Index2   COL1 AVAL   COL2 AVAL
1         1.0  3.0    NaN  NaN
2         3.0  5.0    5.0  8.0
3         NaN  NaN    3.0  7.0

【Python】DataFrame型とSeries型

PandasのDataFrame型とSeries型の備忘録

サンプルデータ


import pandas as pd
group1 = [4, 9, 10, 11, 12, 13, 13, 15, 18, 18, 20]
group2 = [16, 16, 17, 19, 19, 22, 22, 23, 25]


DataFrame型


DataFrame(データフレーム)型は表(テーブル)形式の2次元データ。

addf = pd.DataFrame({"AVAL":group1 + group2
                    ,"TRT01A":["group1"] * len(group1) + ["group2"] * len(group2) })

↓中身

addf.head(5)
Out[1]: 
   AVAL  TRT01A
0     4  group1
1     9  group1
2    10  group1
3    11  group1
4    12  group1
 
type(addf)
Out[2]: pandas.core.frame.DataFrame



Series型


Series(シリーズ)型は1列または1行の1次元データ。

adsr = pd.Series(data=group1, index=range(1,len(group1)+1))

↓ 中身

adsr.head(5)
Out[1]: 
1     4
2     9
3    10
4    11
5    12
dtype: int64
 
type(adsr2)
Out[2]: pandas.core.series.Series


DataFrame型データを1列取り出すと1次元データになるので、Series型と認識される。

adsr2 = addf.loc[addf["TRT01A"]=="group1", "AVAL"]

↓ 中身

adsr2.head(5)
Out[86]: 
0     4
1     9
2    10
3    11
4    12
Name: AVAL, dtype: int64

type(adsr2)
Out[87]: pandas.core.series.Series

【Python】Classの定義(イニシャライザ、継承も含めて)

クラスを試してみる。

クラス、インスタンス、インヘリタンスの定義


・クラス(class):
設計図と言われる。このクラスから実体(インスタンス)を生成する。
クラス自体に実体はない(データを持たない)。

インスタンス(instance):
日本語で実体。
クラスにデータを与えて生成されるもの。
実体を生成することをインスタンス化と言う。

・インヘリタンス(inheritance):
日本語で継承。
親から子へクラスの内容を引き継がせる機能。

Pythonでの実装(クラス定義、インスタンス化)


Pythonでのクラス定義は class クラス名 : と書き、インデントを下げて関数を定義していく。
クラス内の関数はメゾッドと呼ばれ、第一引数で自分自身を定義する必要がある。第一引数の名称は self とする慣習がある。

また、次のコード例で示す def __init__(self, val1...) は特別な関数でイニシャライザと呼ばれる(初期値を与える処理)。

#-----------------------------
#-- クラス定義
#-----------------------------
class MyClass1: 
    def __init__(self, val1, val2):  #-- 初期値を与える
        self.val1 = val1
        self.val2 = val2
    
    def 足し算(self):  #-- メゾッド
        x = self.val1 + self.val2
        print ("足し算:{0}+{1}={2}".format(self.val1,self.val2,x))
 
    def 引き算(self):  #-- メゾッド
        x = self.val1 - self.val2
        print ("引き算:{0}-{1}={2}".format(self.val1,self.val2,x))
 
    def 掛け算(self):  #-- メゾッド
        x = self.val1 * self.val2
        print ("掛け算:{0}×{1}={2}".format(self.val1,self.val2,x))


次に、インスタンス名 = クラス名 (引数) とすることで、定義したクラスに値を与えてインスタンス化する。
そして、インスタンス名.メゾッド名() とすることで、クラス内に定義したメゾッドを実行する。

#-----------------------------
# インスタンス化
#-----------------------------
res1 = MyClass1(1, 2)  #-- インスタンス化(MyClass1に値を与えて実体化する)
  
#-----------------------------
# クラス定義内のメゾッドを実行
#-----------------------------
res1.足し算()
res1.引き算()
res1.掛け算()
 
--- out ---
足し算:1+2=3
引き算:1-2=-1
掛け算:1×2=2


上のコード例の通り、クラス定義により様々な機能を1つの括りでまとめることができる。
大規模な開発になるほど可読性やメンテナンス性などが向上する可能性がある。


Pythonでの実装(継承)


クラスでは親クラス→子クラスに値を引き継がせる継承機能を扱うことができる。

子クラスは class クラス名 (親クラス名) : とする。
この時、子クラス内で super().親クラスのメゾッド(引数名) とすれば、親クラスのメゾッドを呼び出すことができ、同一処理をわざわざ再定義する必要がない。

せっかくなので、これまでの自身の記事を参考にして、
スチューデントのT検定Wilcoxonの順位和検定 を実行できる簡単なパッケージを作ってみる。(※検定名のところに記事のリンク貼っている)

class MyStat1:
    def __init__(self, group1, group2):
        self.group1 = group1
        self.group2 = group2
        self.n1 = len(group1)  #-- グループ1の例数
        self.n2 = len(group2)  #-- グループ2の例数
        self.N  = self.n1 + self.n2  #-- 全体の例数
 
class StudentTtest(MyStat1):
    def __init__(self, group1, group2):
        super().__init__(group1, group2)  #-- 親クラスのイニシャライザを継承
        print("継承しました")  #-- 継承したか見たいだけのプリント
        
    def Diffmean(self):
        import numpy as np
        m1 = np.mean(group1)
        m2 = np.mean(group2)
        return m1 - m2
        
    def TestResult(self):
        import numpy as np
        from scipy import stats
        s1 = np.sum((group1 - np.mean(group1))**2)
        s2 = np.sum((group2 - np.mean(group2))**2)
        Df = self.N - 2
        se = np.sqrt((s1 + s2) / Df)
        T  = self.Diffmean() / (se * np.sqrt(1/self.n1 + 1/self.n2))
        P  = stats.t.cdf(x=T, df=Df)*2
        print(" ----- Student's T-test -----\n"
              ,"T統計量:{0}\n 自由度:{1}\n p値:{2}\n".format(T, Df, P)
              ,"----------------------------")
        return T, Df, P
    
class WilcoxonRankSumTest(MyStat1):
    def __init__(self, group1, group2, ties=True):
        super().__init__(group1, group2)  #-- 親クラスのイニシャライザを継承
        self.ties = ties  #-- Wilcoxonの順位和検定はさらにタイ補正有無の引数を与えてみる
        print("継承しました")  #-- 継承したか見たいだけのプリント
        
    def TestResult(self):
        import numpy as np
        from scipy import stats
        import pandas as pd
        
        #-- データフレーム化
        ads = pd.DataFrame({"AVAL":group1 + group2
                            ,"TRT01AN":["group1"] * self.n1 + ["group2"] * self.n2
                            })
        #-- 全体順位
        ads["Rank"] = ads["AVAL"].rank()
        
        #-- タイ補正(同一順位の数で補正)
        adfrq = ads["AVAL"].value_counts()
        wil_t = np.sum(adfrq**3 - adfrq)
        
        if self.ties == False:
            wil_t = 0  #-- タイ補正しない場合、0に上書き。
        
        #-- 順位和        
        sumrank1 = float(np.sum(ads.loc[ads["TRT01AN"]=="group1", ["Rank"]]))
        sumrank2 = float(np.sum(ads.loc[ads["TRT01AN"]=="group2", ["Rank"]]))
        
        #-- 実測、期待値、分散        
        if sumrank1 < sumrank2:
            wil_W = sumrank1
            wil_E = self.n1 * (self.n1 + self.n2 + 1) / 2
        else:
            wil_W = sumrank2
            wil_E = self.n2 * (self.n1 + self.n2 + 1) / 2
            
        val1 = self.n1 * self.n2 * (self.n1 + self.n2 + 1) / 12
        val2 = self.n1 * self.n2 / (12 * (self.n1 + self.n2) * (self.n1 + self.n2 - 1))
        wil_V = val1 - val2 * wil_t
        wil_Z = (wil_W - wil_E) / np.sqrt(wil_V)
        
        wil_P = stats.norm.cdf(wil_Z)*2
        
        print("----- Wilcoxon Rank Sum Test -----\n"
              ,"順位和:{0} (group1), {1} (group2)\n".format(sumrank1, sumrank2)
              ,"W:{0}\n".format(wil_W)
              ,"E[W]:{0}\n".format(wil_E)
              ,"Var[W]:{0}\n".format(wil_V)
              ,"タイ補正の係数:{0}\n".format(wil_t)
              ,"\n"
              ,"Z統計量:{0}\n".format(wil_Z)
              ,"p値:{0}\n".format(wil_P)
              ,"----------------------------------")
        return wil_Z, wil_P


出来上がったクラスを試してみる。
サンプルデータは Wilcoxonの順位和検定 の記事で扱ったものと同じ。

group1 = [4, 9, 10, 11, 12, 13, 13, 15, 18, 18, 20]
group2 = [16, 16, 17, 19, 19, 22, 22, 23, 25]


T検定(スチューデント)

res1 = StudentTtest(group1, group2)
  
res1.Diffmean()
Out[1]: -6.888888888888889
 
res1.TestResult()
継承しました
 ----- Student's T-test -----
 T統計量:-3.761258193347809
 自由度:18
 p値:0.0014296297831112022
 ----------------------------
Out[1]: (-3.761258193347809, 18, 0.0014296297831112022)


親クラスのN数を self.n1, self.n2, self.N として子クラスで使っているが、問題なく使用できている。
また、StudentTtest クラス内の TestResult メゾッドで、同一クラス内の Diffmean メゾッドを self.Diffmean() で呼び出しているが、こちらも問題はなく動作している。
念のため検算。

from scipy import stats
stats.ttest_ind(group1, group2, equal_var = True)
Out[1]: Ttest_indResult(statistic=-3.7612581933478086, pvalue=0.001429629783111206)


Wilcoxonの順位和検定(タイ補正あり)

res2 = WilcoxonRankSumTest(group1, group2, ties=True)
 
res2.TestResult()
継承しました
----- Wilcoxon Rank Sum Test -----
 順位和:77.0 (group1), 133.0 (group2)
 W:77.0
 E[W]:115.5
 Var[W]:172.59868421052633
 タイ補正の係数:30
 
 Z統計量:-2.930501777999723
 p値:0.00338415057040675
 ----------------------------------
Out[1]: (-2.930501777999723, 0.00338415057040675)


Wilcoxonの順位和検定(タイ補正なし)

res3 = WilcoxonRankSumTest(group1, group2, ties=False)
 
res3.TestResult()
継承しました
----- Wilcoxon Rank Sum Test -----
 順位和:77.0 (group1), 133.0 (group2)
 W:77.0
 E[W]:115.5
 Var[W]:173.25
 タイ補正の係数:0
 
 Z統計量:-2.9249881291307074
 p値:0.0034446936330652616
 ----------------------------------
Out[1]: (-2.9249881291307074, 0.0034446936330652616)


念のため検算。余談だが、stats.ranksumsはタイ補正なしのようだった。

from scipy import stats
stats.ranksums(group1, group2)
Out[2]: RanksumsResult(statistic=-2.9249881291307074, pvalue=0.0034446936330652616)


本記事はここまで。

【Python】関数の作成(def)

関数は「 def 関数名 (引数名) 」とし、インデントを下げてコードを書く。
戻り値は「return 変数名」と書く。なくても良い。

def def_test1(i, j):
    x = i + j
    return x


実行は関数名(引数名)と書く。

val1 = def_test1(1, 2)
print(val1)
  
-- out --
3




もう少し規模大きくして、t 検定(Student)の t 統計量を計算する関数を作ってみる。
計算式は 過去記事 参照。

#-- 関数:T統計量を算出してみる
def ttest1(group1, group2):
    import numpy as np
    m1 = np.mean(group1)
    m2 = np.mean(group2)
    n1 = len(group1)
    n2 = len(group2)
    N  = n1 + n2
    s1 = np.sum((group1 - np.mean(group1))**2)
    s2 = np.sum((group2 - np.mean(group2))**2)
    se = np.sqrt((s1 + s2) / (N - 2))
    t  = (m1 - m2) / (se * np.sqrt(1/n1 + 1/n2))
    return t


実行

group1 = [8,6,7,6,8,9]
group2 = [3,4,3,5,4,6]

ttest1(group1, group2)
 
-- out --
4.608176875690326


stats.ttest_ind関数で答え合わせ。

from scipy import stats
stats.ttest_ind(group1, group2, equal_var = True)
   #-- equal_var=True: Student, False: Welch
 
-- out --
Ttest_indResult(statistic=4.608176875690326, pvalue=0.0009679292740393189)

【Python】条件分岐(if文)やループ処理(while文、for文)

Pythonの基礎。
条件分岐やループ処理について。

if 文


if 文は他の言語と大体同じ。ただし、else if は elif と書く。

a=1
if a==0:
    print(0)
elif a==1:
    print(1)
else:
    print(2)


while 文


while 文は特記なし。よくある形。

cnt=3
while cnt != 0:
    print(cnt)
    cnt -= 1
    if cnt==0:
        print("End!!")
 
-- out --
3
2
1
End!!


continue で強制的に次のループに回す、break で強制的にループを終了できる。

loop_lst=["a", "b", "c", "d", "e"]
cnt = -1
 
while cnt <= len(loop_lst):
    cnt += 1
    print(cnt)
    
    if cnt == 0:
        print("continue!!")
        continue  #-- 以降処理やらず、次のループ処理に回る。
    
    if cnt == 3:
        print("break!!")
        break  #-- ループを終了する
 
-- out --
0
continue!!
1
2
3
break!!


for 文


for の対象の与え方はいくつかある。

・レンジを与える方法

for i in range(0, 10, 2):
    print(i)
 
-- out --
0
2
4
6
8


・リストを与える方法

loop_lst=["a","b","c","d","e"]
 
for i in loop_lst:
    if i == "a":
        print("continue!!")
        continue  #-- 以降処理やらず、次のループ処理に回る。
    
    if i == "d":
        print("break!!")
        break  #-- ループを終了する
        
    print(i)
  
-- out --
continue!!
b
c
break!!


・リストを与える方法(インデックスと値を取得)

for_lst1 = ["a", "b", "c", "d", "e"]
 
for index1, val1 in enumerate(for_lst1): #-- enumerateで囲う
    print("{0} {1} {2}".format(index1, val1, 100 + index1))
 
-- out --
0 a 100
1 b 101
2 c 102
3 d 103
4 e 104


・リストを与える方法(入れ子のリスト)

for_lst2_1 = ["a", "b", "c"]
for_lst2_2 = ["あ", "い", "う"]
 
for i, j, k in [for_lst2_1, for_lst2_2]:
    print("要素1:{0}、要素2:{1}、要素3:{2}".format(i, j, k))
 
-- out --
要素1:a、要素2:b、要素3:c
要素1:あ、要素2:い、要素3:う
 
for i, j in zip(for_lst2_1, for_lst2_2):
    print("リスト1:{0}、リスト2:{1}".format(i, j))
 
-- out --
リスト1:a、リスト2:あ
リスト1:b、リスト2:い
リスト1:c、リスト2:う


・辞書を与える方法(キーを取得)

for_dict1 = {"key1":"a", "key2":"b", "key3":"c"}

#-- keysメゾッドでキーを取得
for key in for_dict1.keys():
    print("キー:{0}".format(key))
 
-- out --
キー:key1
キー:key2
キー:key3


・辞書を与える方法(値を取得)

for_dict1 = {"key1":"a", "key2":"b", "key3":"c"}
  
#-- valuesメゾッドで値を取得
for val in for_dict1.values():
    print("値:{0}".format(val))
 
-- out --
値:a
値:b
値:c


・辞書を与える方法(キーと値を取得)

for_dict1 = {"key1":"a", "key2":"b", "key3":"c"}
 
#-- itemsメゾッドでキーと値を取得
for key, val in for_dict1.items():
    print("キー:{0}、値:{1}".format(key, val))
 
-- out --
キー:key1、値:a
キー:key2、値:b
キー:key3、値:c

【Python】リスト型と辞書型

Pythonを初めるきっかけができたので、ちょくちょくPythonについて取り上げたい。

リスト型と辞書型について


元々SASSQLVBAを中心に使っていたので、Rを使い始めたときにリスト型の概念に初めて触れた。
配列(Array)っぽいと言えばその通りなので特に構えることはないが、使えるようになると便利なのでメモする。

文字、数値、浮動小数点は字の通り。
リスト型は [] で囲う。辞書型は {} で囲い「インデックス:値」とする。

x = "a"  #-- 文字 str
x = 1    #-- 数値 int
x = 1.1  #-- 浮動小数点 float
x = [1, 2, 3]  #-- リスト list
x = {"key1" : "val1", "key2" : "val2", "key3" : "val3"}  #-- 辞書 dict


リスト型


リストはインデックスが 0~始まる。

lst1 = ["A", "B", "C"]
print(lst1[0])
A


リスト内には複数の型を含められる。

lst2 = ["1", 2, 3.1, [1,2,3], {"key1":1,"key2":2}]
  
type(lst2)
Out[1]: list
  
type(lst2[0])
Out[2]: str
  
type(lst2[1])
Out[3]: int
  
type(lst2[2])
Out[4]: float
  
type(lst2[3])
Out[5]: list
  
type(lst2[4])
Out[6]: dict


更新・追加・削除・複製方法は次のとおり。

lst1 = [1, 2, 3, 4]
  
#-- 更新
lst1[0] = 99  #-- インデックス0を1から99に更新
  
#-- 追加
lst1.append(5)  #-- 末尾に値:5 を追加。
lst1 += [6, 7]  #-- 末尾に別のリストを追加。
  
#-- 削除
del lst1[5] #-- インデックス5を削除
  
#-- 複製
lst2 = lst1  #-- この方法だと lst2 の更新が lst1 にも反映されてしまうようである。
lst3 = list(lst1)  #-- そのため、list関数で囲ってコピーする(他にもやり方はある)。



辞書型


辞書型も同じく、複数の型を含めることができる。

dict1={"key1":"1"
       ,"key2":2
       ,"key3":3.1
       ,"key4":[1,2,3]
       ,"key5":{"subkey1":"あ","subkey2":"い"}}
 
type(dict1)
Out[1]: dict
 
type(dict1["key1"])
Out[2]: str
 
type(dict1["key2"])
Out[3]: int
 
type(dict1["key3"])
Out[4]: float
 
type(dict1["key4"])
Out[5]: list
 
type(dict1["key5"])
Out[6]: dict
 
type(dict1["key5"]["subkey1"])
Out[7]: str


更新・追加・削除・複製方法は次のとおり。

dict1 = {"key1" : "a", "key2" : "b", "key3" : "c"}
   
#-- 更新
dict1["key1"] = 99  #-- キー:"key1"を99に更新
print(dict1)
   
#-- 追加
dict1["key4"] = "d"  #-- キー:"key4"、値:"d"を追加。
print(dict1)
 
#-- 削除
del dict1["key4"] #-- キー:"key4"を削除
print(dict1)
   
#-- 複製
dict2 = dict1  #-- この方法だと dict2 の更新が dict1 にも反映されてしまうようである。
dict3 = dict(dict1)  #-- そのため、dict関数で囲ってコピーする(他にもやり方はある)。




この記事はここまで。

【統計】生存時間解析 ハザード関数、生存関数などの関係性

生存時間解析ではハザード関数、生存関数など色々な関数が出てくるので関係性をメモ。頭の整理。

離散値の場合


確率密度関数

\quad f\left(t\right)=Pr\left(T=t\right)

死亡関数

\quad F\left(t\right)=\sum ^{t} _{T=0}f\left(t\right)

生存関数

\quad S\left(t\right)=\sum ^{T} _{t<T}f\left(t\right)=1-F\left(t\right)

ハザード関数

\quad h\left(t\right)=Pr\left(T=t \ | \ T \geqq t \right)=\dfrac{f\left(t\right)}{S\left(t-1\right)}

累積ハザード関数

\quad H\left(t\right)=\sum ^{t} _{T=0}h\left(t\right)


(イメージ図)
f:id:cochineal19:20210328135838p:plain:w300

* 縦軸が確率密度関数 f (T)、横軸が時間 T
* 死亡関数 F(t)=時点tまでにイベント発生する確率
* 生存関数 S(t)=時点t以降も生存している(イベント発生しない)確率。
* ハザード関数 H(t)=時点tの直前まで生存している集団(リスク集団、Number At Risk)のうち、時点tでイベント発生する確率


連続値の場合


確率密度関数

\quad f\left(t\right)=\lim _{\Delta t\rightarrow 0}\dfrac{\Pr \left( t \leqq T < t+\Delta t\right) }{\Delta t}

 ※Δt に依存するため、Δt で割って標準化する。

死亡関数

\quad F\left(t\right)=\int _{0}^{t}f\left( t\right) dt

生存関数

\quad S\left(t\right)=\int _{t}^{\infty }f\left( t\right) dt=1-F\left(t\right)

ハザード関数

\quad h\left(t\right)=\lim _{\Delta t\rightarrow 0}\dfrac{\Pr \left( t \leqq T < t+\Delta t \ | \ T \geqq t \right) }{\Delta t}=\dfrac{f\left(t\right)}{S\left(t\right)}

累積ハザード関数

\quad H\left(t\right)=\int _{0}^{t}h\left( t\right) dt


(イメージ図)
f:id:cochineal19:20210328135917p:plain:w300

打ち切りのあるデータの推定量


打ち切りがなければ、死亡関数から累積生存率を推定できる。

 \quad \widehat{S} \left(t\right)=1 − F\left(t\right)

打ち切りがあれば、カプランマイヤー法による推定(条件付き確率)。

\quad \widehat{S} \left( t \right) = \prod_{t_{i} < t} \left( 1 - \dfrac{d_{i}}{n_{i}} \right)


また、累積生存率から累積ハザード関数を推定できる。

\quad \widehat{H}\left( t\right) = -\log\ \widehat{S}\left( t \right) =\sum \dfrac{d_{i}}{n_{i}}

\quad \log \widehat{H}\left( t\right) = \log\left(-\log\ \widehat{S}\left( t \right)\right)


参考


http://www.math.s.chiba-u.ac.jp/~wang/suvival.pdf
Rと生存時間分析(1)
生存時間分析の基礎1(生存時間分析とは・生存時間分析のデータ形式)|Maxwell|note

本ブログは個人メモです。 本ブログの内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。