## 1からnまでのリストを作る list(range(1,n+1)) ## a ~ b の間でランダムな整数を n個 リスト化する import random [random.randint(a,b) for _ in range(n)] ## 0 ~ 1 の間でランダムな浮動小数点を n個 リスト化する import random [random.random() for _ in range(n)]
SIGNATE Cloud Python入門
s1 = "Data Science Training"
s2 = s1.split() # デフォルトで空白区切で文字列をリスト化してくれる
['Data', 'Science', 'Training']
s3 = ",".join(s2)
Data,Science,Training
s1.replace(" ", "", 回数) # 文字列の置換 ▲リスト型には使えない▼
# リストの場合は s1[0]= などで上書きして直す
s1.strip("Ding") # 文字列の両端から該当文字を削除 データクレンジングに有効かも
s1.lstrip("Da") # 左端から該当文字を削除
s1.rstrip("raining") # 右端から該当文字を削除
print("a" in s1) # True/Falseで返ってくる
s1.find("a") # インデックス番号で返ってくる ▲リスト型には使えない▼
s1.index("a") # リスト用
s1.count("a") # 個数が返ってくる
len(s1) # 文字列の長さ(空白もカウントされる)
s1.isdecimal() # 十進数だけ? True/Falseで返ってくる
s1.isdigit() # 数字だけ?
s1.isnumeric() # 数を表す文字だけ? ほぼ同じみたいだが・・
s1.isalpha() # アルファベット/ひらがな/カタカナ/漢字だけ?
s1.isalnum() # 上記全てに該当する?
s1.isascii() # ASCII文字だけ?
s1.bool() # ブーリアン判定
リスト用
len(lst) # リストの要素数を返す
max(lst) # リストの最大値を返す
min(lst) # リストの最小値を返す
sum(lst) # リストの全要素を足す
lst.index("a") # リストでインデックス番号を返すにはこれ
lst.append(追加要素) # 一番後ろに追加する
lst += 追加要素 でもいける
lst.insert(インデックス番号, 追加要素) # 指定したインデックス番号に差し込む
del s1[3:6] # 3番目から5番目の要素をリストから削除する 特殊な形だねぇ・・
lst.remove("要素") # 要素そのものをリストから削除する
lst.sort() # 昇順に並べ替える ▼print()の中に入れるとNoneになる。sort()実施後に別口でprint()すること。
lst.sort(reverse=True) # 降順に並べ替える ▼print()の中に入れるとNoneになる。sort()実施後に別口でprint()すること。
辞書用
for key in dict.keys(): # 辞書からkeyを取り出してループを回す keys()
for value in dict.values(): # 辞書からvalueを取り出してループを回す values()
for key,value in dict.items(): # 辞書からkeyとvalueを取り出してループを回す items()
重複をなくした降順リストにする
a = [6, 10, 8, 10, 6, 8]
a = sorted(list(set(a)), reverse=True) # set()関数は{dict}が返ってきてしまうので、list()でリストに戻して、最後に降順ソート
# リストからindex番号と値を取り出す
for index,value in enumerate(list):
# 辞書からindex番号と値を取り出す
for key,value in dict.items():
# 0から4までの数字を2乗したリストの変数squareを、内包表記で作成しましょう
square = [i**2 for i in range(5)]
print(square)
# 0から9までの数字で3で割り切れない数のリストの変数non_triを、内包表記で作成しましょう
non_tri = [i for i in range(10) if i%3!=0 ]
print(non_tri)
# リストから辞書を作る
vegetables = ['tomato','cabbage','onion','carrot','cucumber']
vegetables_dict = {e:len(e) for e in vegetables}
変数 = open('Sample.txt','r') # 読み込みモード
変数 = open('Sample.txt','w') # 書き込みモード
open_file = open('Sample.csv','r') # 読み込みモードでファイルを開く
open_file = open('Sample.csv','w') # 書き込みモードでファイルを開く
print(open_file.closed) # ファイルが閉じられているか否か True/False
read_file = open_file.read() # ファイルを全て文字列として読み込む
read_file = open_file.readline() # ファイルを1行だけ文字列として読み込む
read_file = open_file.readlines() # ファイルを全てリストとして読み込む
data = 'id,name,score' # 書き込みたいデータ
list_data = ['id', ',', 'name', ',', 'score'] # 書き込みたいデータ
open_file.write(data) # ファイルにデータを書き込む
open_file.writelines(list_datadata) # ファイルにデータを書き込む
open_file.close() # ファイルを閉じる
print(open_file.closed) # ファイルが閉じられているか否か True/False
with open("data.csv") as open_file: # with構文を使用してファイルを開く
print(open_file.closed) # ファイルが閉じているかを確認する
read_file = open_file.read() # 開いたファイルを読み込む
print(read_file)
print(open_file.closed) # ファイルが閉じているかを確認する
## グラフ描画 df.列名.value_counts().plot(kind="bar") # 要素のユニーク数を棒グラフで表現
Python 機械学習
## データフレーム全体の操作
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline # plt.show()を省略してもグラフが出力される & 2つ以上のグラフを同時に出力できる
# csvファイルの読み込み
pd.read_csv("path.csv", nrows=num, encoding="shift-jis", usecols=["列名1","列名2","列名3"], dtype="str", dtype={"列名":"タイプ"})
# tsvファイルの読み込み
pd.read_csv("path.tsv", sep="\t")
# Excelファイルの読み込み
pd.read_excel("path.xlsx")
# データフレームの作成
pd.DataFrame( { "列名": [1,2,3,4] } ) # データフレームを作成する時は、辞書型で書く { "列名":[リスト] }
# データフレームの縦結合
pd.concat([df1, df2]) # CONCATnate デフォルトで 縦 に連結
pd.concat([df1, df2], axis=1) # 横 に連結
# データフレームの横結合
pd.merge(df1, df2, on="結合キー列", how="inner")
# how=inner 内部結合 / outer 完全外部 / left 左外部 / right 右外部
## 行・列の操作
# カラム名の変更
df.rename(columns={"現カラム名":"新カラム名"})
# 外れ値を含む列
df.列名.clip(lower=引数, upper=引数) # 下限と上限を決めて外れ値を収める どちらか片方でも可
# 欠損値を含む行
df.isnull().any() # 欠損値が存在するかを確認
df.isnull().sum() # 欠損値の個数を確認
df.列名.fillna(df.列名.mode()[0]) # 最頻値で埋める
df.dropna() # 欠損値を含む行を削除
df.dropna(subset="列名") # 指定した列に欠損値を含む行を削除
df.dropna(subset=["列名1", "列名2"]) # 複数列を指定して、いずれかに欠損値を含む場合は行削除
df.drop_duplicates(subset=["列名1", "列名2", "列名3"]) # 重複行を削除 ※subsetに書いた列で重複判定して削除する
df.drop_duplicates(keep="last") # 最後のレコードを残して削除
df.drop_duplicates(keep="False") # 重複しているものは1行たりとも残さず全て削除
## レコードの絞り込み
> < より大きい / 未満(より小さい)
>= <= 以上 / 以下
& かつ
| または ※ and とか or とか not は使えない★
~ でない(反転)
# 単一条件に合ったレコードを抽出
df[df.列名 == num] # 数値とが等しいレコードを抽出★
df[df.列名 == "str"] # 文字列と等しいレコードを抽出★
df.query("列名 == num") # strの場合は'シングル'クォーテーションで括る★
df.列名[df.列名 != num] # 値と等しくないレコードを抽出
df.query("列名 != 'str'") # strの場合はシングルクォーテーションで括る
# 複数条件に合ったレコードを抽出
df[(df["列名1"]=="str") & (df["列名2"]>=num)] # 1つ1つの条件文を、丸括弧 ( ) で囲むのを忘れずに★
df.query("列名1 == 'str' & 列名2 > num") # and strの場合はシングルクォーテーションで括る
df.query("列名1 != 'str' | 列名2 > num") # or strの場合はシングルクォーテーションで括る
# str.contains()メソッドを使用したレコード抽出
df[df.列名.str.contains("〇〇")] # リストの中身はTrue/Falseが返っている
df[df.列名.str.contains("\(株\)")] # (株) のように半角カッコを含む場合は、直前に \ を置いてメタ文字エスケープ
# 日付の範囲でレコード抽出
import datetime # datetime64[ns]タイプの[date]列から抽出する例
df.query("datetime.datetime(2024,7,1) < date < datetime.datetime(2024,8,31)") # 指定した期間
# [y]列が数値だったら
df.query("y < datetime.datetime.now().year") # 去年までのもの
# 列名1でグルーピングして、列名2で集計
df.groupby("列名1")["列名2"].mean().reset_index(drop=True/False) # 平均値だけ # 旧indexをdropする/しない
df.groupby("列名1")["列名2"].agg(["mean","median"]).reset_index() # 平均値と中央値
# 列名1と列名2でグルーピングして、列名3で集計
df.groupby(["列名1","列名2"])["列名3"].mean().reset_index() # 複数項目のクロス集計
# 列名1でグルーピングして、列名2と列名3で違う集計を行う
df.groupby("列名1").agg({"列名2":"mean", "列名3":"median"}).reset_index()
# 固定長文字列の抽出 ★ 0 スタートなので注意
df.列名.apply(lambda x: x[0]) # 先頭文字を抽出
df.列名.apply(lambda x: x[-1]) # 末尾文字(右から1文字目)を抽出
df.列名.apply(lambda x: x[3:5]) # 4文字目と5文字目を抽出
df.列名.apply(lambda x: x[:3] # 先頭から3文字目まで抽出
df.列名.apply(lambda x: x[3:] # 4文字目から最後まで抽出
# 可変長文字列の抽出
指定文字で左右に分割してリスト化し、要素として抽出することで実現
df.列名.apply(lambda x: x.split(", ")[2]) # ', 'で区切った3番目の文字列を抽出
df.列名.apply(lambda x: x.split(" ")[1]) # 半角空白の後ろの文字列を抽出
df.列名.apply(lambda x: x.split("@")[0]) # メアドからユーザ名を抽出
df.列名.apply(lambda x: x.split("@")[1]) # メアドからドメイン名を抽出
## データの集計
df.shape # 行列数
df.size # データサイズ(欠損値を含むデータの個数)
df.列名.nunique() # ユニーク数
df.列名.unique() # ユニークな要素の一覧
df.sort_values(by="列名", na_positon="first/last", ascending=True) # 単一カラム
df.sort_values(by=["列名1","列名2"], ascending=[True,False]) # 複数カラム
df.列名.value_counts(ascending=True) # 要素別の頻度(出現回数)と昇順True, 降順False
df.列名.value_counts(normalize=True) # 割合として表示(出現回数を正規化してる)
df.列名.value_counts().sort_values(ascending=True)
df.列名.sum() # 合計値
df.列名.mean() # 平均 と★
df.列名.std() # 標準偏差 を並べて表示すると、68%範囲の目星がつく★
df.列名.median() # 中央値
df.列名.mode()[0] # 最頻値
df.列名.min() # 最小値
df.列名.max() # 最大値
print(df.列名.max() - df.列名.min()) # データの範囲も見てみよう
print((df.列名1.mean() - df.列名2.mean()) *100 - 100) # 平均値の変化率[%]▲
df.groupby.列名.sum() # グルーピングして合計を算出
df.groupby.列名.mean() # グルーピングして平均を算出
df.pivot_table(index="列名1", columns="列名2", values="計算対象の列名", aggfunc="sum") # 合計値のクロス集計★
df.pivot_table(index="列名1", columns="列名2", values="計算対象の列名", aggfunc="mean") # 平均値のクロス集計★
df.corr() # 相関係数(-1~+1) # これだけでは不十分で、★
※df.plot.scatter(x="列名1", y="列名2") # 散布図を併用しないと重要な相関を見逃す★
# ランキング
df.列名.rank(ascending=False/True, method="min/max") # False 降順 / True 昇順
# method= min(最小値が順位となる) / max(最大値が順位となる) / デフォルトは average(平均が順位となる)
dense(最小値が順位となり、後続の順位を詰める)
## 描画 df.列名.hist() # ヒストグラムで分布をみる df.列名.plot(kind="hist") df.列名.plot.box() # 箱ひげ図で分布を見る df.列名.plot(kind="box") ※df.corr() # 相関係数(-1~+1) # これだけでは不十分で、★ df.plot.scatter(x="列名1", y="列名2") # 散布図を併用しないと重要な相関を見逃す★ plt.show() # 描画
## 正規表現
import re
^ 先頭
$ 末尾
. 任意の1文字
? 0回または1回 不特定の1文字
* 0回以上の繰り返し 不特定の複数文字
+ 1回以上の繰り返し
# 抽出
re.search("抽出したい文字列パターン", "対象文字列").group() # groupで結果の取り出し 使い方わかんねぇぇ
df.query("列名.str.contains('^J.*A$', regex=True)", engine="python") # Jから始まりAで終わるもの
df.query("列名.str.contains('[6-8]$', regex=True)", engine="python") # 6,7,8のいずれかで終わるもの
# 置換
re.sub("置換したい文字列パターン", "置換後の文字列", 置換対象)
使い方例
df.列名.apply(lambda x: re.sub("※.*", "", x)) # ※以降の文字列を全て消し去る
## 文字列操作 ★ df["new"] = で、新たな列に結果を出力した方がいいかもね
# 文字列の結合
df.列名1 + df.列名2
df.apply(lambda x: x.列名1 + x.列名2, axis=1)
df.apply(lambda x: x[列名1] + x[列名2], axis=1)
# 文字列の置換
df.列名.map({"置換前":"置換後"})
df.列名.replace({"置換前":"置換後"})
# 文字列の置換・消去
df.列名.apply(lambda x: x.replace("置換対象文字列", "置換後の文字列"))
あるある
df.社名.apply(lambda x: x.replace("(株)", "株式会社")) (株)を株式会社に置換
df.電話番号.apply(lambda x: x.replace("-", "")) ハイフンを消す
# nanに置換
import math
import numpy as np
df.loc["インデックス名", "列名"] = math.nan | np.nan
# 大文字・小文字揃え
df.列名.apply(lambda x: x.upper())
df.列名.apply(lambda x: x.lower())
# 半角・全角揃え
import mojimoji
df.列名.apply(lambda x: mojimoji.han_to_zen(x)) # 半角→全角
df.列名.apply(lambda x: mojimoji.zen_to_han(x)) # 全角→半角
# ビニング
df["bin"] = pd.cut(df.列名, bins=["区切1","区切2","区切3","区切4"], right=False, labels=["Aランク","Bランク","Cランク"])
# right=False/Trueエッジをどちらに含めるか False 20 <= value < 30 True 20 < value <= 30
確認
df.bin.value_counts() # bin列でカウントして数が多い順に表示
df.bin.mode()[0] # 最頻値だけを表示
# インデックスの振りなおし
df.reset_index(drop=True) # drop=Trueにすると、元のインデックス列を削除
# 日付型への変換 ★ df["new"] = で、新たな列に結果を出力した方がいいかもね
import pandas as pd
pd.to_datetime(df.列名)
pd.to_datetime(df.列名, format="%Y年%m月%d日")
例
df["今日"] = "8月7日2024年" # 新たな列を作って
df["今日"] = pd.to_datetime(df["今日"], format="%m月%d日%Y年") #
↑
df["今日"] = pd.to_datetime("2024/8/7") # てか1行で書ける
# 日付型から要素を抜き出す ★ df["new"] = で、新たな列に結果を出力した方がいいかもね
x.year:年
x.month:月
x.day:日
x.hour:時
x.minute:分
x.second:秒
x.weekday_name:曜日
例
df['年'] = df.生年月日.apply(lambda x: x.year)
df['月'] = df.生年月日.apply(lambda x: x.month)
df['日'] = df.生年月日.apply(lambda x: x.day)
df[["年","月","日"]]
# 日付型から差分を知る
df['今日'] = pd.to_datetime('2024/8/7')
df['経過日数'] = df.apply(lambda x: (x['今日']-x['生年月日']).days, axis=1) ▲後でちゃんと調べる
df['年齢'] = df['経過日数']//365 # 切り捨て除算
モジュール
FizzBuzzナベアツ風
for i in range(1,41):
if i%3 == 0 or 3 in list(map(int,str(i))):
print(i,"(アホ)")
else:
print(i)
>・・・
[8]
[9]
[1, 0]
[1, 1]
・・・
完全数を求める
%%time
# 自分を含まない約数の総和を求める関数
def divisors(n):
div = []
for i in range(1,n):
if n%i==0:
div.append(i)
if sum(div)==n:
return sum(div)
n = int(input())
print(f'{n} までの間に完全数があるか計算中…')
# 1~nの間で、完全数があるかを求める
for i in range(1,n+1):
if divisors(i)==i:
print(i)
>10000 までの間に完全数があるか計算中…
6
28
496
8128
CPU times: total: 891 ms
Wall time: 4.1 s
文字列操作
数値→リスト変換 一桁ずつstrとして分割し、intに変換してリストに格納
n = 123456789 lst = [int(x) for x in list(str(n))] print(lst) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
リスト→数値変換 リストの要素を一つずつstrとして取り出して繋いで、intに変換
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9] from functools import reduce # reduceモジュールの読み込みが必要 result = int(reduce(lambda x, y: x + y, [str(x) for x in lst])) # reduceで文字列+文字列を畳み込んでいく print(result) # 123456789
転じてリスト結合にも使える
lst1 = [1, 2, 3, 4, 5] lst2 = [6, 7, 8, 9, 10] result = reduce(lambda x, y: x + y, [lst1, lst2]) print(result) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
高階関数
ポイントは、関数を渡す際に () が無いこと
map()
関数を適用して結果をイテレータで返す
基本形:result = list(map(関数, イテラブル, イテラブル, ….)) ※イテラブルは複数でも可
# イテラブルオブジェクト1つの例
def square(x): # 値を2乗する関数
return x**2
lst = [1, 2, 3, 4, 5]
result = list(map(square, lst)) # 戻り値はイテレータなのでlist()に入れる
print(result)
# [1, 4, 9, 16, 25]
# ↓
# これをlambda式で表すと
lst = [1, 2, 3, 4, 5]
result = list(map(lambda x: x**2, lst))
print(result)
# [1, 4, 9, 16, 25]
# イテラブルオブジェクト2つの例
def square_cube(x,y): # 第1引数は値を2乗、第2引数は値を3乗する関数
return x**2, y**3
lst1 = [1, 2, 3, 4, 5]
lst2 = [6, 7, 8, 9, 10]
result = list(map(square_cube, lst1, lst2)) # 戻り値はイテレータなのでlist()に入れる
print(result)
# [(1, 216), (4, 343), (9, 512), (16, 729), (25, 1000)]
# ↓
# これをlambda式で表すと
lst1 = [1, 2, 3, 4, 5]
lst2 = [6, 7, 8, 9, 10]
result = list(map(lambda x,y:(x**2, y**3), lst1, lst2)) # lambda式の複数計算は()で囲えばタプルで返るし、[]で囲えばリストで返る
print(result)
# [(1, 216), (4, 343), (9, 512), (16, 729), (25, 1000)]
filter()
関数の条件を満たす要素を抽出してイテレータを返す
基本形:result = list(filter(関数, イテラブル)) ※イテラブルは1つのみ
# イテラブルオブジェクトの例
def is_odd(x): # 奇数を判別する関数
return x % 2 != 0
lst = [1, 2, 3, 4, 5]
result = list(filter(is_odd, lst))
print(result)
# [1, 3, 5]
# ↓
# これをlambda式で表すと
lst = [1, 2, 3, 4, 5]
result = list(filter(lambda x: x % 2 != 0, lst)) # 戻り値はイテレータなのでlist()に入れる
print(result)
# [1, 3, 5]
reduce()
指定した関数を使って、イテラブルの要素を畳み込む
基本形:from functools import reduce ※モジュールの読み込みが必要(Python3から)
result = reduce(関数, イテラブル)
from functools import reduce # モジュールの読み込み
# 加算の畳み込み
def add_nums(x, y):
return x + y
lst = [1, 2, 3, 4, 5]
result = reduce(add_nums, lst)
print(result)
# 15
# ↓
# これをlambda式で表すと
lst = [1, 2, 3, 4, 5]
result = reduce(lambda x, y: x + y, lst)
print(result)
# 15
# 乗算の畳み込み
def multiply_nums(x, y):
return x * y
result = reduce(multiply_nums, lst)
print(result)
# 120
# ↓
# これをlambda式で表すと
lst = [1, 2, 3, 4, 5]
result = reduce(lambda x, y: x * y, lst)
print(result)
# 120
便利な使い方
リストの要素を一つずつstrとして取り出して繋ぎ、intに変換することができる
from functools import reduce # モジュールの読み込み
def add_nums(x, y):
return x + y # ここでは加算ではなく文字列の繋げ合わせの意味
lst = [1, 2, 3, 4, 5]
result = int(reduce(add_nums, [str(e) for e in lst]))
print(result)
# 12345
# ↓
# これをlambda式で表すと
lst = [1, 2, 3, 4, 5]
result = int(reduce(lambda x, y: x + y, [str(e) for e in lst]))
print(result)
# 12345
partial()
対象の関数と、関数で固定したい引数の値を「引数=値」という形で指定。
引数を指定値で固定した「関数」が戻り値となり、以降の処理でfunc()として実行できる。
基本形:from functools import partial ※モジュールの読み込みが必要
func = partial(関数, 引数=値)
from functools import partial # モジュールの読み込み # べき乗する pow関数(組み込み) を使用した例 func2 = partial(pow, exp=2) # べき乗の係数を2で固定 print(func2(2)) print(func2(3)) # 4 # 9 func3 = partial(pow, exp=3) # べき乗の係数を3で固定 print(func3(2)) print(func3(3)) # 8 # 27