[[Pythonバイオ]] ~
&counter();   &lastmod();~

*pandasティップス [#gfafdcc8]

**行選択と列選択 [#s06c1b34]
***行位置選択 [#ocd73bc9]

***行の値選択、列の値選択 [#c8f0f893]

**セル選択 [#l2d0b6fa]

**行演算と列演算 [#g8a09294]

**2列間での演算 [#b2cbdb07]
[[Pandasで複数の列を値をもとに、新しい列を任意の関数で定義する方法 | Shikoan's ML Blog:https://blog.shikoan.com/pandas-newcolumn-lambda/]]

 import pandas as pd
 comike = pd.DataFrame({
     "block" : ["AX", "AY", "あZ", "あX", "イQ", "イR"],
     "number" : [1, 1, 10, 11, 12, 13],
     "side" : ["aX", "bX", "aY", "bZ", "aQ", "bR"]
 })
 print(comike)
 #comike["space"] = comike.apply(lambda x: f"{x['block']}-{x['number']:02d}{x['side']}", axis=1)
 comike = comike[comike.apply(lambda x: x['block'][1]==x['side'][1], axis=1) ]
 print(comike)

**値・行名/列名でソートする [#n7f98c79]
[[pandas.DataFrame, Seriesをソートするsort_values, sort_index | note.nkmk.me:https://note.nkmk.me/python-pandas-sort-values-sort-index/]]

値でソートする
 df.sort_values()
 df.sort_values(ascending=False)
行名でソートする
 df.sort_index()
列名でソートする
 df.sort_index(axis=1)


**ifのある内包 [#nc7b9210]
 even_list = [i for i in range(10) if i % 2 == 0]

 even_list = [i if i % 2 == 0 else "odd" for i in range(10)]

**三項演算子(条件式) [#b032fe2b]
[[Pythonの三項演算子(条件演算子)でif文を一行で書く | note.nkmk.me:https://note.nkmk.me/python-if-conditional-expressions/]]~
[[6. 式 (expression) — Python 3.8.0 ドキュメント 6.12. 条件式 (Conditional Expressions):https://docs.python.org/ja/3/reference/expressions.html#conditional-expressions]]
 result = a * 2 if a % 2 == 0 else a * 3

elifを含めたい時(推奨せず)
 result = 'negative' if a < 0 else 'positive' if a > 0 else 'zero'

**要素データの置き換え replace [#h8fdf3a7]
[[pandas.DataFrame, Seriesの要素の値を置換するreplace | note.nkmk.me:https://note.nkmk.me/python-pandas-replace/]]
 df = df.replace(oldvalue, newvalue)

**列名の付け替え rename [#bbba1027]
[[pandas.DataFrameの行名・列名の変更 | note.nkmk.me:https://note.nkmk.me/python-pandas-dataframe-rename/]]
 df = df.rename(columns={旧名: 新名, 旧名2: 新名2, ...})

なお、indexに対する名前を付けるには
 df.index.name = colname1
同様に、
 df.columns.name = colname2
つまり
 import pandas as pd
 df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], columns=['A','B','C'])
 print(df)
 df.index.name='インデックス'
 print(df)
 df.columns.name = 'カラム'
 print(df)
とすると、何もつけないときは
    A  B  C
 0  1  2  3
 1  4  5  6
 2  7  8  9
indexに名前'インデックス'を付けると
         A  B  C
 インデックス         
 0       1  2  3
 1       4  5  6
 2       7  8  9
更に、columnに名前'カラム'を付けると
 カラム     A  B  C
 インデックス         
 0       1  2  3
 1       4  5  6
 2       7  8  9
となる。

**インデックスの付け替え  drop_indexとset_index [#b993a345]
[[pandas.DataFrame, Seriesのインデックスを振り直すreset_index | note.nkmk.me
https://note.nkmk.me/python-pandas-reset-index/]]
 df = df.drop_index()  # インデックスは新たに列として加えられる。もし列名が重複するとエラー

 df = df.drop_index(drop=True)  # インデックスを完全に削除(列として残さない)

 df = df.set_index('列名')  # 列名の列をインデックスとして使う。その列は消える

 df = df.reset_index.set_index('列名') # 元のインデックスを列として残しつつ変更

**列位置の入れ替え [#ffcfd8c3]
 df = df.loc[:, ["col3", "col1", "col2", "col0"]]

**行・列のdrop [#z8e03439]
[[pandas.DataFrameの行・列を指定して削除するdrop | note.nkmk.me:https://note.nkmk.me/python-pandas-drop/]]
 df = df.drop('行名', axis=0)   # axis=0はデフォルト
 df = df.drop(index='行名')
 df = df.drop('列名', axis=1)
 df = df.drop(column='行名')
複数行・列の場合
 df = df.drop(index=['行名1', '行名2']

行番号で指定
 df = df.drop(index=df.index[1, 3, 5]))

なお、値を条件にして行を削除/残すのは、
 df = df[df['参照']>=3]
 df = df[(df['参照1']>=3) and (df['参照2']!='')]
でできる。

**列名が重複してしまった時の列の削除 [#bf69d059]
 import pandas as pd
 df = pd.DataFrame([['A',1, 0.1], ['B', 2, 0.2], ['C', 3, 0.3], ['D', 4, 0.4]], 
 columns=['ラベル', '値', '値'])
 print(df)
 #  ラベル  値    値
 #0   A  1  0.1
 #1   B  2  0.2
 #2   C  3  0.3
 #3   D  4  0.4
 
 dfx = df[['ラベル', '値']]    # 値は2つ残る
 print(dfx)
 #  ラベル  値    値
 #0   A  1  0.1
 #1   B  2  0.2
 #2   C  3  0.3
 #3   D  4  0.4
 
 dfx = df.drop('値', axis=1)   # 2つともdropする
 print(dfx)
 #  ラベル
 #0   A
 #1   B
 #2   C
 #3   D
 
 dfx = df.drop(df.columns[[2]], axis=1)  # 位置2を指定しても2つともdropする
 print(dfx)
 #  ラベル
 #0   A
 #1   B
 #2   C
 #3   D
 
 dfx = df.copy()   # 浅いコピーだと列名書換えはdfの方にも及ぶので注意
 dfx.columns = ['ラベル', '値', '値2']   # すべて指定すれば列名はすべて書き変えられる
 dfx = dfx[['ラベル', '値']]   # 値2をdropすればいい
 print(dfx)
 #  ラベル  値
 #0   A  1
 #1   B  2
 #2   C  3
 #3   D  4
 
 dfx = df.rename(columns={'値': '値3'})  # 両方とも書き換えられる
 print(dfx)
 #  ラベル  値3   値3   <-- 両方とも'値3'になるのでダメ
 #0   A   1  0.1
 #1   B   2  0.2
 #2   C   3  0.3
 #3   D   4  0.4

結論として、列名を全面的に書換えするしかなさそうだ。

**DataFrameから辞書 [#n9c1c571]
[[pandas.DataFrame, Seriesを辞書に変換(to_dict) | note.nkmk.me:https://note.nkmk.me/python-pandas-to-dict/]]

DataFrameの2つの列の間の関係を辞書にするためには、
-キー側の列の値をindexとし、
-値を(列値として)並べた
-Seriesを作る
そのSeriesを、ser.to_dict() で辞書型に変換する

**Series/DataFrameからリストに変換するなら to_list() [#zff41b08]
[[pandas.DataFrame, SeriesとPython標準のリストを相互に変換 | note.nkmk.me:https://note.nkmk.me/python-pandas-list/]]

Seriesの値部分だけなら
 s = pd.Series([0, 1, 2])
 l_1d = s.values.tolist()

DataFrameの値部分だけなら
 df = pd.DataFrame([[0, 1, 2], [3, 4, 5]])
 l_2d = df.values.tolist()
 print(l_2d)
 # [[0, 1, 2], [3, 4, 5]]

行ラベル(行名)ともリストに変換するには、結局reset_indexとかでインデックスを列に含める
 l_1d_index = s_index.reset_index().values.tolist()
 print(l_1d_index)
 # [['row1', 0], ['row2', 1], ['row3', 2]]

列ラベル(列名)はreset_indexに相当する機能が無いので、1つの方法として転置してからreset_indexをかける。
 l_2d_index_columns = df_index.reset_index().T.reset_index().T.values.tolist()
 print(l_2d_index_columns)
 # [['index', 'col1', 'col2', 'col3'], ['row1', 0, 1, 2], ['row2', 3, 4, 5]]

ラベルだけなら、df.index、df.columnsだが、リストにするためにtolist()しておく
 df.index.tolist()
 df.columns.tolist()

**重複した行をdropする [#dacc5443]
[[duplicatedとdrop_duplicates:https://note.nkmk.me/python-pandas-duplicated-drop-duplicates/]]
 df = df.duplicated(keep='last', subset=['この列での重複']) # 重複ならTrue、ないならFalseの1列
 df = df[~df.duplicated(keep='...', subset=['..', '..'])]  # 重複以外をひろう(=drop_duplicates)
 
 df = df.drop_duplicates(keep='last')  # 重複した列を最後の1つだけ残して削除

**文字列を含む行の抽出 [#g058fbd0]
[[pandasで特定の文字列を含む行を抽出(完全一致、部分一致) | note.nkmk.me:https://note.nkmk.me/python-pandas-str-contains-match/]]

完全一致は == でよい。
 dfx = df[df['state'] == 'CA']

部分一致は、in はダメらしい。str.contains() を使う。
 dfx = df[df['name'].str.contains('li')

但し、デフォルトでは第1引数を正規表現と解釈する(要するにre.searchと同様)ので、
ピリオド等を含む場合には正しくない。回避するためには regex=False を指定するとよい。
 dfx = df[df['name'].str.contains('li', regex=False)

また、要素が欠損値NaNである場合、デフォルトではNaNを返すので、行を抽出するとエラーになる。オプションとして na=True/False を指定する。
 dfx = df[df['name'].str.contains('li', na=True)]   # NaNは抽出結果に含まれる
 dfx = df[df['name'].str.contains('li', na=True)]   # NaNは抽出結果に含まない

なお、str.containsの他、 str.startswith や str.endswidth 更に str.match(〜re.matchと同様の動作) が使える。

**要素が指定リストに含まれる行の抽出 (文字列ではなくてリスト) [#h6f9b92f]
[[pandas.DataFrameの行を条件で抽出するquery | note.nkmk.me:
https://note.nkmk.me/python-pandas-query/]]

基本的に、isinメソッドを使うか、queryメソッドの中で in を使うか。
 dfx = df[df['state'].isin(['NY', 'TX'])]
か
 dfx = df.query('state in ["NY", "TX"]')
これも可:
 dfx = df.query('state == ["NY", "TX"]'

**Groupby [#u931854d]
[[pandas.DataFrameをGroupByでグルーピングし統計量を算出 | note.nkmk.me:https://note.nkmk.me/python-pandas-groupby-statistics/]]
 grouped = df.groupby('グループ化したい列名')
この結果に対して統計演算ができる
 df = grouped.sum()
使えるのはsum(), mean(), min(), max(), std(), var()など

また、agg()を使って、関数を適用することができる。関数はSeriesを受け取って
objectを返す関数でなければならない。
 df = grouped.agg(lambda x: type(x))['sl'])
 df = grouped.agg(min)
列ごとに異なる関数を適用することも可能。
 df = grouped.agg({'列1': min}, {'列2': max})

複数の列をキーにしてグループ化できる。
 gf = df.groupby(['列1', '列2']).mean()

as_index=Falseを指定すると(True時はキーが結果DFのインデックスになるが)、キーは結果DFの行のままで残りインデックスは元のまま
 df = pd.DataFrame({
     'city': ['osaka', 'osaka', 'osaka', 'osaka', 'tokyo', 'tokyo', 'tokyo'],
     'food': ['apple', 'orange', 'banana', 'banana', 'apple', 'apple', 'banana'],
     'price': [100, 200, 250, 300, 150, 200, 400],
     'quantity': [1, 2, 3, 4, 5, 6, 7]
 })
 
 gb = df.groupby(['city', 'food']).mean()  # as_index指定なし(デフォルトはTrue)
 print(gb)
に対して
                price  quantity
 city  food                   
 osaka apple   100.0       1.0
       banana  275.0       3.5
       orange  200.0       2.0
 tokyo apple   175.0       5.5
       banana  400.0       7.0

だが、as_index=Falseにすると
 gb_noindex = df.groupby(['city', 'food'], as_index=False).mean()
 print(gb_noindex)
に対して
      city    food  price  quantity
 
 0  osaka   apple  100.0       1.0
 1  osaka  banana  275.0       3.5
 2  osaka  orange  200.0       2.0
 3  tokyo   apple  175.0       5.5
 4  tokyo  banana  400.0       7.0

のようにcityとfoodの列が残る。

**Groupbyのグループを取出す [#t7c1b24c]
[[Pandas の groupby の使い方 - Qiita:https://qiita.com/propella/items/a9a32b878c77222630ae]]

df.groupby('city').groups

 {'osaka': Int64Index([0, 1, 2, 3], dtype='int64'),
  'tokyo': Int64Index([4, 5, 6], dtype='int64')}

df.groupby('city').get_group('osaka')

 city	food	price	quantity
 0	osaka	apple	100	1
 1	osaka	orange	200	2
 2	osaka	banana	250	3
 3	osaka	banana	300	4

df.groupby('city').size()

 city
 osaka    4
 tokyo    3
 dtype: int64

df.groupby('city').size()['osaka']
 4

**map, apply [#f837b768]
[[pandasで要素、行、列に関数を適用するmap, applymap, apply | note.nkmk.me:https://note.nkmk.me/python-pandas-map-applymap-apply/]]


**複数dfをjoin [#g92089e4]
[[reference:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.join.html]]

DFのリスト joinlist = [df1, df2, ..., dfn] を用意し、dfにjoinする。
 dfout = df.join(joinlist)
このとき、キー指定("on"の指定)はできない。インデックスをキーにしてjoinする。

つまり、あらかじめインデックスを付け替えておく必要がある。
 df1 = df1.set_index('column to use as key')

**NaN扱い [#s643db78]
NaNはnumpyのnan

DFでなければ
 if np.isnan(np.nan):
     hogehoge

DFでのnan判定

[[Reference→API reference のgeneral function:https://pandas.pydata.org/pandas-docs/stable/reference/general_functions.html#top-level-missing-data]]にある
 df = pd.DataFrame8{[1,3],[2,np.nan]])
 print(df.isnull())
 print(df.notnull())
なお、isnull()はisna()のalias、notnull()はnotna()のalias


**初めに空のDataFrameを作って後からデータ行を足す [#u5bf5dd4]
 df = pd.DataFrame( columns=['A', 'B'] )
 for u in [0, 1, 2, 3]:
     temp_series = pd.Series( [i, i*i], index=df.columns )
     df = df.append( temp_series, ignore_index=True )


**read_csvとto_csv [#uc197a4a]
***read_csv [#c3b65411]
[[pandasでcsv/tsvファイル読み込み(read_csv, read_table) | note.nkmk.me:https://note.nkmk.me/python-pandas-read-csv-tsv/]]~
[[pandas.read_csv &#8212; pandas 0.25.0 documentation:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html]]~
[[codecs &#8212; Codec registry and base classes &#8212; Python 3.7.4 documentation:https://docs.python.org/3/library/codecs.html#standard-encodings]]

 import pandas as pd
 pd.read_csv('filename', sep='\t', header=0, skiprows=[], encoding='cp932')

または
 with open('filename', 'r', encoding='...') as fin:
     pd.read_csv(fin, ... )

なお、separatorが複数空白を含むとき、
 pd.read_csv('filename', sep='\s+')
が使える。[[python - How to make separator in pandas read_csv more flexible wrt whitespace? - Stack Overflow:https://stackoverflow.com/questions/15026698/how-to-make-separator-in-pandas-read-csv-more-flexible-wrt-whitespace]]

***to_csv [#v2cce651]
 df = ...
 df.to_csv('filename', ...)


**read_excelとto_excel [#of1b91ac]
[[pandas.DataFrame.to_excel &#8212; pandas 0.25.0 documentation:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_excel.html]]

If you wish to write to more than one sheet in the workbook, it is necessary to specify an ExcelWriter object:

 >>> df2 = df1.copy()
 >>> with pd.ExcelWriter('output.xlsx') as writer:  # doctest: +SKIP
 ...     df1.to_excel(writer, sheet_name='Sheet_name_1')
 ...     df2.to_excel(writer, sheet_name='Sheet_name_2')

**ヒストグラム [#ic4eefe7]

**散布図 [#h1e623b6]

**ヒートマップ [#z0569817]

**階層的クラスタリング [#uec2b39e]
 import numpy as np
 from scipy.cluster.hierarchy import dendrogram, linkage
 from scipy.spatial.distance import pdist
 import matplotlib.pyplot as plt
 X = np.array([[1,2], [2,1], [3,4], [4,3]])
 Z = linkage(X, 'single')  # ward法を使うならば 'single' の代わりに 'ward' を指定する
 dendrogram(
     Z,
     leaf_font_size=8.,  # font size for the x axis labels
 )
 plt.show()

 %matplotlib inline
 import pandas as pd
 import matplotlib.pyplot as plt
 from scipy.cluster.hierarchy import linkage, dendrogram
 df_count_tpm = pd.read_csv("count_tpm.tsv", sep="\t", index_col=0)
 tpm_t = df_count_tpm.T
 print(df_count_tpm.head())
 from scipy.spatial.distance import pdist
 linkage_result = linkage(tpm_t, method='average', metric='correlation')
 plt.figure(num=None, figsize=(16, 9), dpi=200, facecolor='w', edgecolor='k')
 dendrogram(linkage_result, labels=df_count_tpm.columns)
 plt.show()

**k-means法によるクラスタリング [#g269d509]

**mySQLアクセス [#mb48d1b0]
 def read_db(query):
     engine = create_engine('mysql+mysqldb://userid:password@localhost/dbname?charset=utf8',\
                            echo=False)
     dfr = pd.io.sql.read_sql(query, engine)
     return(dfr)
 
 query = 'select * from tablename'
 df = read_db(query)

**ファイルの存在 [#ead665d2]
 import os
 path = "./sample"
 os.path.exists(path)

**pickle [#r9cb401a]
 with open(picklefname, 'rb') as pf:
     df = pickle.load(pf)

 with open(picklefname, 'wb') as pwf:
     pickle.dump(df, pwf)


** 条件式(3項演算子) [#g859559a]
 x = "OK" if n == 10 else "NG"

**文字列のリストを繋いで1つの文字列にする [#ec82a71e]
 s = ''
 for u in list:
    s += u

'間に挿入する文字列'.join([連結したい文字列のリスト])
 s = ''.join(list)

**文字列の検索 [#i02e3afc]
 >>> "spam".find("pa")
 1
 >>> "spam".find("x")
 -1
indexは見つからないときにエラーを返す

**Seriesに2引数の関数をapplyする場合 [#k62ded28]
 df.x.apply(f1, args=(2,))
 # または、 apply にキーワード引数で与える
 df.x.apply(f1, b=2)

**DF内の検索 [#t51adbc8]
 df[X].isin([list])  listでなければならない。

**pandasで任意の位置の値を取得・変更するat, iat, loc, iloc [#r3974ed5]
 https://note.nkmk.me/python-pandas-at-iat-loc-iloc/

**argv, argc [#v0ea81c0]
 import sys
 argvs = sys.argv;
 argc = len(argvs)
 if (argc != 2):
     print('Usage: python %s filename' % argvs[0])
     quit()

**リストのソート [#k7cb2fe9]
 newls = sorted(list)
メソッドsortはin-placeでソートするので注意。
 list.sort()  # listそのものが置き換わる

**グローバル変数 [#hd2fe0e1]
https://uxmilk.jp/12505
 var = 1
 def add_ten(x):
     global var
     var = 10
     print var + x
  
 add_ten(2)    # 12
 print var     # 10

**リストの差分 [#w1338c7e]
https://python.ms/sub/optimization/if-vs-try/list-deletion/#_6-1-1-%E6%AF%94%E8%BC%83%E5%AF%BE%E8%B1%A1
 def subtract_list(lst1, lst2):
     lst = lst1.copy()
     for e2 in lst2:
         try:
             lst.remove(e2)
         except ValueError:
             continue
     return lst
ifでチェックするより早い

**型のチェック [#yf21f317]
特にNaNがあると、NaNはfloat型だと思い込むので、後の処理でぶつかることがある。

その時に、型チェックで逃げるとすると、(pandas的には個別の型チェックよりはdropnaなどの方がいいと思うが)必要になる。

[[Pythonで型を取得・判定するtype関数, isinstance関数 | note.nkmk.me:https://note.nkmk.me/python-type-isinstance/]]

なのだが、isinstance()の方がよさそうだ。typeで引っかかない場合がある。

**列の型変換 [#la791077]
 df['innings'].astype(np.int64)

**リストの任意の位置への項目挿入 [#aa79d344]
 list.insert(位置, 値)
リストを置き換えるので注意


**絶対値 pythonのabsとmathのfabs、numpyのabs(absolute)、fabs [#z9e9ee09]
pythonのabsは、整数の絶対値は整数、小数の絶対値は小数、複素数の絶対値も可。

mathのfabsは、整数に対しても小数に対しても、絶対値は小数を返す。複素数は不可。

numpyのabs(=absoluteと書いてもいいらしい)は配列ndarrayに対しても適用できる。
もし整数と小数が混ざっていると、小数にする(最大精度)。

numpyのfabsはmathのfabsと同様に、必ず小数を返す。複素数は不可。

**ヒストグラム・カウント [#s4f2f043]
 df.hist()
 (df['column']).hist()
 (df['column']).value_counts()
 (df['column']//10*10).value_counts()

カウント結果はSeriesなので、
 s = pd.Series([3, 2, 7, 2, 3, 4])
 u = s.value_counts(sort=False)
 print(u)
 # 2    2
 # 3    2
 # 4    1
 # 7    1
 
 print(type(u))
 <class 'pandas.core.series.Series'>
 
 print(u.index)
 Int64Index([2, 3, 4, 7], dtype='int64')
 
 # カウント結果uをindexでソートすると(黙っていると値の降順でソート)
 print(u.sort_index(ascending=False))
 # 7    1
 # 4    1
 # 3    2
 # 2    2



〜〜〜〜〜〜〜〜〜〜〜〜

**おまけ bashのループ [#m8969d16]
 #!/usr/bin/bash
 samples=("Anc" "1_2-1" "2_2-1" "2_5-1" "2_5-1-7A" "1_2-2" "2_2-2" "2_6-2" "2_6-2-10E")
 for f in "${samples[@]}"
 do
   #nohup python ProcessGD.py $f > $f.out &
   echo $f
 done

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS