Pandasの各列を引数で渡し、行ごとに処理する

よく忘れるので自分的なメモです。

import pandas as pd

def my_func(row):
	d = row['A'] + row['B'] + row['C']
	if row['A'] > 6:
		d = 10
	return d

df = pd.read_excel('Book1.xlsx')
print(df)

df['D'] = df.apply( my_func, axis=1)
print(df)
    A       B   C
0   1   100.0   9
1   2   500.0  67
2   3    40.0  45
3   4     5.0  34
4   5     5.4   2
5   6     7.0   1
6   7    90.0   4
7   8    74.0   5
8   9  1000.0   6
9  10    40.0   7
    A       B   C      D
0   1   100.0   9  110.0
1   2   500.0  67  569.0
2   3    40.0  45   88.0
3   4     5.0  34   43.0
4   5     5.4   2   12.4
5   6     7.0   1   14.0
6   7    90.0   4   10.0
7   8    74.0   5   10.0
8   9  1000.0   6   10.0
9  10    40.0   7   10.0

GO言語(golang)でテキストファイルをAES暗号化する

AES(Advanced Encryption Standard)は強度が極めて高いと言われている共通鍵暗号化方式の一つで、アメリカ政府が政府内の標準として策定した暗号化規格です。

C#とPythonではプログラムを書いたことがありますが、golangではどうするのだろうと思い、作ってみました。

プログラムの主要部分はこちらのサイトを参考にさせていただきました。

以下、暗号化するプログラムです。

package main

import (
	"fmt"
	"io/ioutil"
	"gopkg.in/alecthomas/kingpin.v2"
	"github.com/howeyc/gopass"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
)

func main() {
	var (
		in   = kingpin.Arg("infile", "Input text File Name").Required().String()
		out   = kingpin.Arg("outfile", "Output text File Name").Required().String()
	)

	//コマンドライン引数を受け取る
	kingpin.Parse()
	fmt.Println("input  txt file :", *in)
	fmt.Println("output txt file :", *out)

	for {
			//16文字のパスワード入力
			fmt.Printf("Enter 16 bytes password: ")
			Password, err := gopass.GetPasswdMasked()
			if err != nil{
				fmt.Println(err)
			}
			if len(Password) == 16 {
				//テキストファイル読み込み
				plainText, err := ioutil.ReadFile(*in)
				if err != nil {
					panic(err)
				}
				//鍵の設定
				block, err := aes.NewCipher([]byte(Password)); if err != nil {
					fmt.Println(err)
				}
				//ガロアカウンタモードのブロック暗号
				gcm, err := cipher.NewGCM(block); if err != nil {
					fmt.Println(err)
				}
				//一度きりの初期化ベクトル作成
				nonce := make([]byte, gcm.NonceSize())
				_, err = rand.Read(nonce); if err != nil {
					fmt.Println(err)
				}
				cipherText := gcm.Seal(nil, nonce, plainText, nil) //暗号化
				cipherText = append(nonce, cipherText...) //初期化ベクトルを先頭に付与

				//Base64 Encode
				sEnc := base64.StdEncoding.EncodeToString(cipherText)
				err = ioutil.WriteFile(*out, []byte(sEnc), 0644); if err != nil {
					fmt.Println(err)
				}

				break

			} else {
				fmt.Println("Password not equal 16 bytes")
			}
		}
}
cat test.txt

Hello World !
あいうえお
かきくけこ
①②③④⑤
go run encaes.go test.txt out.txt

input  txt file : test.txt
output txt file : out.txt
Enter 16 bytes password: ****************
cat out.txt

v3rnUlLk5kha6smtAtNq2hDBrOSFQTg8jM702TQv/pgsouvQX9vlmQlWRQEh76kNcz+muHnhKXygBwqarjWNakNKxup+uZ46Jl5x+dmXF8XCAKauUs8RMoks

そして、以下が複合するプログラムです。

package main

import (
	"fmt"
	"io/ioutil"
	"gopkg.in/alecthomas/kingpin.v2"
	"github.com/howeyc/gopass"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
)

func main() {
	var (
		in   = kingpin.Arg("infile", "Input text File Name").Required().String()
		out   = kingpin.Arg("outfile", "Output text File Name").Required().String()
	)

	//コマンドライン引数を受け取る
	kingpin.Parse()
	fmt.Println("input  txt file :", *in)
	fmt.Println("output txt file :", *out)

	for {
			//16文字のパスワード入力
			fmt.Printf("Enter 16 bytes password: ")
			Password, err := gopass.GetPasswdMasked()
			if err != nil{
				fmt.Println(err)
			}
			if len(Password) == 16 {
				//暗号化されたBase64テキストファイルの読み込み
				sEnc, err := ioutil.ReadFile(*in)
				if err != nil {
					panic(err)
				}
				cipherText, _ := base64.StdEncoding.DecodeString(string(sEnc))
				//鍵の設定
				block, err := aes.NewCipher([]byte(Password)); if err != nil {
					fmt.Println(err)
				}
				//ガロアカウンタモードのブロック暗号
				gcm, err := cipher.NewGCM(block); if err != nil {
					fmt.Println(err)
				}
				//先頭に追加された初期化ベクトルを取り出す
				nonce := cipherText[:gcm.NonceSize()]
				plainByte, err := gcm.Open(nil, nonce, cipherText[gcm.NonceSize():], nil); if err != nil {
					fmt.Println(err)
				}
				err = ioutil.WriteFile(*out, []byte(plainByte), 0644); if err != nil {
					fmt.Println(err)
				}

				break

			} else {
				fmt.Println("Password not equal 16 bytes")
			}
		}
}
go run decaes.go out.txt dec.txt

input  txt file : out.txt
output txt file : dec.txt
Enter 16 bytes password: ****************
cat dec.txt

Hello World !
あいうえお
かきくけこ
①②③④⑤

GO言語でExcelを読み書きする

なぜgolang(GO言語)かというと「pythonは遅く(速く実行させる方法もあります)golangは速い」

そして「コンパイル型の言語であり、生成されたネイティブコードはそれを実行する為に何らかの実行環境を用意する必要がない」

さらに「クロスコンパイル言語であり、MacOSでWindowsやLinuxの実行ファイルを生成できる。またその逆も可能である」

ということが魅力だからです。
場面によっては、Pythonではなくgolangで作る必要があるかと思います。

golangの環境構築は様々なサイトに情報があります。
また、Excelを読み書きする為のパッケージはxuriさん公開されています。

読み込むExcel
VisualStudioCodeでgolang

ということで、CSVファイルを読み込んで既存のExcelファイルに放り込む簡単なプログラムを作成してみました。

package main

import (
	"fmt"
	"encoding/csv"
	"os"
	"log"
	"io"
	"strconv"

	"github.com/360EntSecGroup-Skylar/excelize"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	csvfile   = kingpin.Arg("csvfile", "CSV File Name").Required().String()
	excelfile = kingpin.Arg("excelfile", "Excel File Name").Required().String()
	sheetname = kingpin.Arg("sheet", "Excel Sheet Name").Required().String()
	address = kingpin.Arg("address", "Address ex) A1").Default("A1").String()
)

func main() {

	// コマンドラインパラメータを受け取る
	kingpin.Parse()
	fmt.Println("CSV File Name    :", *csvfile)
	fmt.Println("Excel File Name  :", *excelfile)
	fmt.Println("Excel Sheet Name :", *sheetname)
	fmt.Println("Address          :", *address)

	// CSVファイルオープン
	fcsv, err := os.Open(*csvfile)
	if err != nil {
		log.Fatal(err)
	}
	// 貼り付ける先頭アドレスの数値を取得
	col, row, err := excelize.CellNameToCoordinates(*address)

	//Excelファイルオープン
	//エラーの場合は新規作成(ここは要注意)
	//他のプロセスがファイルにアクセスしていてもエラーになる?
	fexcel, err := excelize.OpenFile(*excelfile)
	if err != nil {
		fexcel = excelize.NewFile()
		fmt.Println(err)
		fmt.Println("Created a new book  :", *excelfile)
	}

	// Sheetがなければ作成する
	index := fexcel.GetSheetIndex(*sheetname)
	if index == -1 {
		m := fexcel.NewSheet(*sheetname)
		if m < 0 {
			fmt.Println("sheet create err :", *sheetname)
		}
		fmt.Println("Created a new sheet :", *sheetname)
	}

	// CSVの読み込み
	r := csv.NewReader(fcsv)
	rowcount := 0
	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		// CSVの各行毎にExcelのSheetに出力
		for i, v := range record {
			cellName, err := excelize.CoordinatesToCellName(col + i, row + rowcount)
			if err != nil {
				log.Fatal(err)
			}
			val, err := strconv.ParseFloat(v, 64)
			if err != nil {
				fexcel.SetCellValue(*sheetname, cellName, v)
			} else {
				fexcel.SetCellValue(*sheetname, cellName, val)
			}
		}
		rowcount += 1
	}
	err = fexcel.SaveAs(*excelfile)
	if err != nil {
		log.Fatal(err)
	}
}
Book.xlsx

python-docxでtableを結合する

以下では書類の向きを横向きにして2行2列の表を作成し、2行目を結合してそれぞれに画像を貼り付けています。

from docx import Document
from docx.shared import Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.enum.section import WD_ORIENT

doc = Document()

section = doc.sections[-1]
new_width, new_height = section.page_height, section.page_width
section.orientation = WD_ORIENT.LANDSCAPE
section.page_width = new_width
section.page_height = new_height

tables = doc.add_table(2, 2)
tables.alignment = WD_TABLE_ALIGNMENT.CENTER

a = tables.cell(1, 0)
b = tables.cell(1, 1)
A = a.merge(b)

p = doc.tables[0].rows[0].cells[0].paragraphs[0]
p.alignment=WD_ALIGN_PARAGRAPH.CENTER
r = p.add_run()
r.add_picture('1.jpg',width=Cm(8.0), height=Cm(6.0))
r.add_break()
r.add_text('風景1')

p = doc.tables[0].rows[0].cells[1].paragraphs[0]
p.alignment=WD_ALIGN_PARAGRAPH.CENTER
r = p.add_run()
r.add_picture('2.jpg',width=Cm(8.0), height=Cm(6.0))
r.add_break()
r.add_text('風景2')

p = doc.tables[0].rows[1].cells[1].paragraphs[0]
p.alignment=WD_ALIGN_PARAGRAPH.CENTER
r = p.add_run()
r.add_picture('3.jpg',width=Cm(8.0), height=Cm(6.0))
r.add_break()
r.add_text('風景3')

doc.add_page_break()

doc.save('test.docx')
結合された表を含むWord文章
結合された表を含むWord文章

結合したセルにアクセスするには、

p = doc.tables[0].rows[1].cells[0].paragraphs[0]

としても良いし、

p = doc.tables[0].rows[1].cells[1].paragraphs[0]

としても良いようです。

また、書類を横向きにするためには

section.orientation = WD_ORIENT.LANDSCAPE

とするだけではダメで、

section.page_width
section.page_height

を書き換えてサイズを変更する必要があります。

python-docxでWORD文章に表を作成して画像とテキストを貼り付ける

以下、サンプルです。

from docx import Document
from docx.shared import Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT

doc = Document()

tables = doc.add_table(rows=3, cols=2)
tables.alignment = WD_TABLE_ALIGNMENT.CENTER

count = 0
for i in range(3):
	for j in range(2):
		count += 1
		fname = str(count) + '.jpg'
		s = '風景' + str(count)
		p = doc.tables[0].rows[i].cells[j].paragraphs[0]
		p.alignment=WD_ALIGN_PARAGRAPH.CENTER
		r = p.add_run()
		r.add_picture(fname,width=Cm(8.0), height=Cm(6.0))
		r.add_break()
		r.add_text(s)

p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
r = p.add_run()
r.add_text('6つの風景')

doc.save('test.docx')
test.docx

Pyfemap(Python版、FEMAPのAPI)でグループ毎のリナンバー

以下、サンプルです。

existObj = pythoncom.connect(Pyfemap.model.CLSID)
app = Pyfemap.model(existObj)
xyz = list()
xyz.append(6)
xyz.append(2)
xyz.append(4)

elemSET = app.feSet
gr = app.feGroup
gr.Get(1) #グループ番号1
rc = gr.GetList(constants.FGR_ELEM, elemSET.ID)
rc =  app.feRenumberOpt2(constants.FT_ELEM, elemSET.ID, 1001, 6, 0, False, False, False, xyz) # 1001を先頭にして要素番号をリナンバー
rc = app.feSetFree(elemSET.ID)

点のポリゴン内外判定

必要に応じて、様々の言語で作ったことがあります。

しかし、Pythonのsympyを使えば簡単。

from sympy.geometry import Point, Polygon

x = list()
y = list()

px = 0.5
py = 0.5

x.append(0.0)
x.append(1.0)
x.append(1.0)
x.append(0.0)

y.append(0.0)
y.append(0.0)
y.append(1.0)
y.append(1.0)

points = list()
for i,X in enumerate(x):
	p = Point(X, y[i])
	points.append(p)

poly = Polygon(*points)
point = Point(px, py)

print(poly.encloses_point(point))
True

ポリゴンを構成する線上や構成ポイント上はFalseになります。

Python版AEiで二分探査法

Python版のAEiを作成しました。
手始めに、Calculixの接触問題で入力荷重を変化させ、二分探査法により歪が特定の値となる荷重値を求めるデモを作成しました。

解析を実行するスクリプトは以下のとおり。

import sys
import AEpy as AEI

pmax = 1.0
pmin = 0.1
target = 2.0e-5

while (pmax - pmin) > 1.0e-6:
	pmid = (pmax + pmin) / 2.0
	BASE = 'case_test'
	INP = BASE + '.inp'
	DAT = BASE + '.dat'
	FRD = BASE + '.frd'
	AEI.a('FRDNAME', FRD)
	AEI.a('MYLOAD',pmid, 'L')
	AEI.b('bolt_tmp.txt', INP)
	AEI.b('cgx.txt', 'my.frd')
	AEI.c('ccx ' + BASE)
	AEI.c('cgx -b my.frd')
	AEI.c('python my_max.py ' + DAT + ' result.csv')
	M = AEI.d('result.csv')
	eps = float(M[0][0])
	print('LOAD=', pmid, 'eps=', eps, 'target=', target)
	if eps > target:
		pmax = pmid
	else:
		pmin = pmid

Pythonデータ解析最強パッケージpandas

先の、AEiで連続SR解析を実行する解析コントロールのExcelファイルの全シートを読み込むプログラムです。

コメントや空白行を除けばたった4行。
最強です。

import pandas as pd

# pandas でExcelの全シートを読み込む(ヘッダ行、インデクス列の指定なし)
df_sheet_all = pd.read_excel('analysis.xlsx', sheet_name=None, header=None, index_col=None)

# 全シートの総ての内容を表示する
for df in df_sheet_all:
    print(df, '\n', df_sheet_all[df])

出力は以下です。
numpyの機能ですが、大量のデータが記載されたシート(WAVE)の出力が逸品です。

case 
      0     1             2      3         4     5
0   No    地盤           入力波  入力波番号  入力波ステップ数  建屋減衰
1   01   std  EL_CENTRO_NS      1      2201  0.05
2   02   std     BASE_WAVE      2      6000  0.05
3   03   std  HACHINOHE_NS      3      3600  0.05
4   04  psig  EL_CENTRO_NS      1      2201  0.05
5   05  psig     BASE_WAVE      2      6000  0.05
6   06  psig  HACHINOHE_NS      3      3600  0.05
7   07  msig  EL_CENTRO_NS      1      2201  0.05
8   08  msig     BASE_WAVE      2      6000  0.05
9   09  msig  HACHINOHE_NS      3      3600  0.05
10  10   std  EL_CENTRO_NS      1      2201  0.03
11  11   std     BASE_WAVE      2      6000  0.03
12  12   std  HACHINOHE_NS      3      3600  0.03
13  13  psig  EL_CENTRO_NS      1      2201  0.03
14  14  psig     BASE_WAVE      2      6000  0.03
15  15  psig  HACHINOHE_NS      3      3600  0.03
16  16  msig  EL_CENTRO_NS      1      2201  0.03
17  17  msig     BASE_WAVE      2      6000  0.03
18  18  msig  HACHINOHE_NS      3      3600  0.03
WAVE 
             0             1          2             3
0     time(s)  EL-CENTRO-NS  BASE_WAVE  HACHINOHE_NS
1        0.01       0.01689          0       -0.3047
2        0.02     -0.006061          0       -0.3287
3        0.03      -0.02901          0       -0.3389
4        0.04      -0.05195          0       -0.3417
5        0.05      -0.07489          0        -0.336
6        0.06      -0.05591     0.0001        -0.331
7        0.07      -0.02954     0.0001        -0.336
8        0.08     -0.003163     0.0002       -0.3482
9        0.09       0.02322     0.0003       -0.3476
10        0.1       0.04959     0.0005        -0.324
11       0.11       0.06019     0.0007       -0.2741
12       0.12       0.03569     0.0009       -0.2038
13       0.13       0.01116     0.0011       -0.1215
14       0.14      -0.01336     0.0011       -0.0418
15       0.15      -0.03789     0.0011        0.0193
16       0.16       -0.0624     0.0009        0.0576
17       0.17      -0.08694     0.0007        0.0764
18       0.18      -0.05936     0.0004        0.0584
19       0.19      -0.02848     0.0001        0.0141
20        0.2      0.002398    -0.0003       -0.0124
21       0.21       0.03329    -0.0008       -0.0356
22       0.22       0.06416    -0.0014       -0.0394
23       0.23       0.09505    -0.0022       -0.0212
24       0.24       0.06195    -0.0029        0.0238
25       0.25       0.01758    -0.0036          0.06
26       0.26      -0.02679    -0.0042        0.0952
27       0.27      -0.07115    -0.0047        0.1139
28       0.28      -0.07003    -0.0052        0.0944
29       0.29      -0.04939    -0.0056        0.0467
...       ...           ...        ...           ...
5971    59.71             0    -0.0942             0
5972    59.72             0    -0.0969             0
5973    59.73             0    -0.0764             0
5974    59.74             0    -0.0399             0
5975    59.75             0     0.0037             0
5976    59.76             0      0.039             0
5977    59.77             0     0.0619             0
5978    59.78             0     0.0718             0
5979    59.79             0     0.0776             0
5980     59.8             0     0.0832             0
5981    59.81             0     0.0894             0
5982    59.82             0     0.0926             0
5983    59.83             0     0.0887             0
5984    59.84             0     0.0756             0
5985    59.85             0     0.0596             0
5986    59.86             0     0.0448             0
5987    59.87             0     0.0341             0
5988    59.88             0     0.0265             0
5989    59.89             0     0.0189             0
5990     59.9             0     0.0125             0
5991    59.91             0     0.0132             0
5992    59.92             0      0.024             0
5993    59.93             0     0.0429             0
5994    59.94             0     0.0637             0
5995    59.95             0     0.0845             0
5996    59.96             0     0.0961             0
5997    59.97             0     0.1022             0
5998    59.98             0     0.1007             0
5999    59.99             0     0.0939             0
6000       60             0     0.0847             0

[6001 rows x 4 columns]
std 
     0            1     2      3     4     5  6
0  No            G    VS      ρ     ν    層厚  h
1   1  1.12487e+08   250  17650  0.45  4.55  2
2   2  1.12487e+08   250  17650  0.45  4.55  2
3   3  1.12487e+08   250  17650  0.45   4.2  2
4   4  1.12487e+08   250  17650  0.45   4.2  2
5   5  1.12487e+08   250  17650  0.45   0.9  2
6   6  1.12487e+08   250  17650  0.45   0.9  2
7   7  5.17608e+09  1500  22560  0.37   100  2
psig 
     0            1     2      3     4     5  6
0  No            G    VS      ρ     ν    層厚  h
1   1   1.3611e+08   275  17650  0.45  4.55  2
2   2   1.3611e+08   275  17650  0.45  4.55  2
3   3   1.3611e+08   275  17650  0.45   4.2  2
4   4   1.3611e+08   275  17650  0.45   4.2  2
5   5   1.3611e+08   275  17650  0.45   0.9  2
6   6   1.3611e+08   275  17650  0.45   0.9  2
7   7  6.26306e+09  1650  22560  0.37   100  2
msig 
     0            1     2      3     4     5  6
0  No            G    VS      ρ     ν    層厚  h
1   1  9.11148e+07   225  17650  0.45  4.55  2
2   2  9.11148e+07   225  17650  0.45  4.55  2
3   3  9.11148e+07   225  17650  0.45   4.2  2
4   4  9.11148e+07   225  17650  0.45   4.2  2
5   5  9.11148e+07   225  17650  0.45   0.9  2
6   6  9.11148e+07   225  17650  0.45   0.9  2
7   7  4.19262e+09  1350  22560  0.37   100  2