2015-01-30

Commonality Analysis

Commonality Analysis(日本語では共通性分析と呼ぶらしい)とは、一連のデータに潜む共通性を見つけ出すための解析です。そのため、状況によって解析のアプローチは様々ですが、今回は、複数ある製造工程において、収率に影響を与える工程を見つけ出すケースを扱います。

LOTIDSTAGE_ASTAGE_BSTAGE_CSTAGE_DSTAGE_ESTAGE_FYIELD
P01A01B01C01D01E01F0194.08
P02A01B02C04D02E03F0192.84
P03A02B03C01D01E01F0396.52
P04A02B01C03D03E02F0496.34
P05A02B03C02D02E03F0194.11
P06A01B01C03D01E03F0394.36
P07A03B02C02D02E01F0493.14
P08A02B02C01D01E02F0294.94
P09A03B03C02D03E03F0496.33
P10A01B03C03D03E02F0398.81
P11A03B01C01D01E01F0296.13
P12A02B02C01D01E01F0294.26
P13A01B02C04D02E01F0292.06
P14A03B01C03D02E02F0195.94
P15A03B03C02D02E03F0498.62
P16A02B02C03D01E01F0393.24
P17A01B01C04D03E01F0394.23
P18A01B03C03D03E02F0494.32
P19A02B03C02D02E03F0196.16
P20A03B02C01D03E02F0291.78

例題

ある製造工程において、最近の 20 ロット (LOTID) の製品収率 (YIELD) の結果が右表のようになりました。収率とは、製品の最終テストにおいて、良品としてパスした同一ロット中の製品比率のことで、単位は % です。

この製品の製造工程には、STEP_A から STEP_F までの 6 工程があり、それぞれの工程で複数の装置(A01, A02, A03 など)のどれかを使用しています。これら複数の装置は区別なく使用できるようになっています。右の表には、それぞれの工程で使用した装置の履歴も加えられています。

区別なく使用できる工程内の複数の装置は、処理性能が製造要求仕様を満たすような範囲に収まるように調整されていますが、全く同一の性能というわけではありません。また、仕様で規定していない特性や性能などについてズレがある場合もあります。

このような状況で、各工程の装置差(ここでは機差と呼ぶことにします)が収率に影響を与えていないかどうかを調査することが今回のテーマです。

このような機差解析をすることを Tool Commonality Analysis と呼んでいます。

とりあえず、収率 (YIELD) のトレンドチャートを作成して、ばらつき具合をみることにしましょう。

R を起動して、クリップボードにコピーした右表を、データフレーム tbl に取り込みます。

$ R

R version 3.1.2 (2014-10-31) -- "Pumpkin Helmet"
...
(省略)
...
 'q()' と入力すれば R を終了します。 

> tbl <- read.table("clipboard", header = T)
> tbl
   LOTID STAGE_A STAGE_B STAGE_C STAGE_D STAGE_E STAGE_F YIELD
1    P01     A01     B01     C01     D01     E01     F01 94.08
2    P02     A01     B02     C04     D02     E03     F01 92.84
3    P03     A02     B03     C01     D01     E01     F03 96.52
4    P04     A02     B01     C03     D03     E02     F04 96.34
5    P05     A02     B03     C02     D02     E03     F01 94.11
6    P06     A01     B01     C03     D01     E03     F03 94.36
7    P07     A03     B02     C02     D02     E01     F04 93.14
8    P08     A02     B02     C01     D01     E02     F02 94.94
9    P09     A03     B03     C02     D03     E03     F04 96.33
10   P10     A01     B03     C03     D03     E02     F03 98.81
11   P11     A03     B01     C01     D01     E01     F02 96.13
12   P12     A02     B02     C01     D01     E01     F02 94.26
13   P13     A01     B02     C04     D02     E01     F02 92.06
14   P14     A03     B01     C03     D02     E02     F01 95.94
15   P15     A03     B03     C02     D02     E03     F04 98.62
16   P16     A02     B02     C03     D01     E01     F03 93.24
17   P17     A01     B01     C04     D03     E01     F03 94.23
18   P18     A01     B03     C03     D03     E02     F04 94.32
19   P19     A02     B03     C02     D02     E03     F01 96.16
20   P20     A03     B02     C01     D03     E02     F02 91.78
> 

次に、横軸に LOTID、縦軸に YIELD をとってトレンドチャートを作成します。

> plot(1:20, tbl$YIELD, xlab = "LOTID", ylab = "YIELD", type = "o", xaxt = "n")
> axis(1, 1:20, tbl$LOTID, las = 2)

トレンドチャートをみて、収率が低いロットを抽出すると以下のようになります。

LOTIDSTAGE_ASTAGE_BSTAGE_CSTAGE_DSTAGE_ESTAGE_FYIELD
P02A01B02C04D02E03F0192.84
P07A03B02C02D02E01F0493.14
P13A01B02C04D02E01F0292.06
P16A02B02C03D01E01F0393.24
P20A03B02C01D03E02F0291.78

各工程の処理装置を見比べると、STAGE_B の装置 B02 が収率の低いロットにおいて共通して使用されていることが判ります。この結果から、装置 B02 が収率に影響を与えていると結論できます。次のステップとして、工程 STAGE_B における装置 B02 の詳細な調査に入ることになるでしょう。

分散分析による Tool Commonality Analysis

今回の例では、トレンドチャートから低収率のロットを抜き出して整理することによって、共通する処理装置を容易に見つけ出すことができました。データが 20 ロット、6 工程程度であれば、あまり苦にならない作業かもしれませんが、工程やロットの数がもっと多くなれば、この方法では、なかなか大変な作業になりそうです。

そこで、一元配置の分散分析を利用して Tool Commonality Analysis をする方法を紹介します。下記のスクリプト commonality.R に示しました。このスクリプトでは、上記 20 ロットの収率データを CSV ファイルとして読み込むようにしています。そのため、その CSV ファイルは sample_commonality.csv.zip からダウンロードできるようにしてあります。

リスト:commonality.R 
require("tcltk")

###############################################################################
# pval.oneway
###############################################################################
pval.oneway <- function(src, x.label, y.label) {
  tmp <- data.frame(X = src[, x.label], Y = src[, y.label])
  result.test <- oneway.test(Y ~ X, data = tmp, var.equal = TRUE)
  return(result.test$p.value)
}

###############################################################################
# chart.boxplot
###############################################################################
chart.boxplot <- function(src, x.val, y.val, gTitle = "", x.label = "", y.label = "") {
  tmp <- data.frame(x = src[, x.val], y = src[, y.val])
  y_max <- max(tmp$y, na.rm = TRUE)
  y_min <- min(tmp$y, na.rm = TRUE)
  y.limit <- c(y_min, y_max)
  
  boxplot(y ~ x, data = tmp, ylim = y.limit,
          main = gTitle, xlab = x.label, ylab =y.label,
          col = "LightBlue", cex.main = 1, outcol = "Orchid")
}

###############################################################################
# MAIN
###############################################################################

# READ CSV DATA
file.name <-tclvalue(tkgetOpenFile(filetypes="{{CSV} {.csv}}", title = "Open CSV file"))
tbl.data <- read.csv(file.name, header = T, as.is = T)

# first column should be always LOTID
# last column should be always YIELD
n.col <- length(tbl.data)
list.stage <- names(tbl.data)[2:(n.col - 1)]
yield <- names(tbl.data)[n.col]

# CHECK 1-WAY ANOVA
df <- data.frame(STAGE = list.stage, P.VALUE = rep(1, length(list.stage)))
for (stage in list.stage) {
  pval <- pval.oneway(tbl.data, stage, yield)
  df[df[, "STAGE"] == stage, "P.VALUE"] <- pval
  # SIGNIFICANT LEVEL: p-value < 0.02 
  if (pval < 0.02) {
    grpTitle <- paste(stage, "\np-value = ", format(pval, digits = 2))
    chart.boxplot(tbl.data, stage, yield, grpTitle, "EQUIPMENT", "YIELD [%]")
    df[df[, "STAGE"] == stage, "SIG"] <- "*"
  } else {
    df[df[, "STAGE"] == stage, "SIG"] <- ""    
  }
}
print(df)

実行例を下記に示します。R を起動して、source コマンドでスクリプトを読み込みます。

$ R

R version 3.1.2 (2014-10-31) -- "Pumpkin Helmet"
...
(省略)
...
 'q()' と入力すれば R を終了します。 

> source("commonality.R")
 要求されたパッケージ tcltk をロード中です 

読み込む CSV ファイルを選択します。

各工程毎に、装置を因子(水準)とした収率の一元配置分散分析を実施します。

帰無仮説 H0 は、『工程 STAGE_X における装置 X01, X02 ... による処理によって、収率に差は生じない』になります。この例では、有意水準を 2% としています。p-value が 2% 未満の工程には、この工程の機差が収率に影響を与えている可能性を示すアスタリスク * を SIG (Significant) の列に付けています。

    STAGE     P.VALUE SIG
1 STAGE_A 0.678511601    
2 STAGE_B 0.001784216   *
3 STAGE_C 0.239092024    
4 STAGE_D 0.849674707    
5 STAGE_E 0.435107778    
6 STAGE_F 0.422098879    
> 

また、p-value が 2% 未満の工程については、装置別のボックスプロットが作成されます。

先の低収率のロットを抽出して分析した結論と同じく、分散分析でも STAGE_B における機差が収率に与える影響を無視できない(有意である)、という結果になりました。

分散分析を利用した Tool Commonality Analysis は、半導体デバイス製造のような長大な製造工程や、大量の生産ロットのデータ解析に威力を発揮します。定常的にこのようなチェックをすることで、収率に影響を与える機差を少なくする活動に繋げるためのシグナル(=機差が有意となる工程)を検出することができます。

ただし、この例のような装置の組み合わせは、あとで解析することを考慮して決められてはいない、ということに注意する必要があります。収率に対して装置の組み合わせが似ている(交絡している)工程で、どちらも有意になる可能性があります。この場合、どちらか、あるいは両方共、偽のシグナルになるかもしれません。しかし、詳細な調査を始めるための十分なヒントになるでしょう。

複数の工程の効果を分離して解析するためには、各因子の効果を分離できるように組み合わせが考慮された、すなわち、デザイン(計画)された、実験を行う必要があります。

しかし、実験計画法 (DOE) を量産ラインに適用するにはコストが掛かります。因子の交絡による偽シグナルがあることを認識した上で、今回のような Tool Commonality Analysis を繰り返すことで、真のシグナル(収率に影響を与える工程)を炙り出すというアプローチは、生産情報をそのまま利用する安価かつリアルタイムなアプローチと言えるかもしれません。

関連サイト

  1. R-Source - 68. 多群の検定

 

2015-01-28

【まとめ】Firefox OS 搭載スマートフォン Fx0

au から昨年末に発売された Firefox OS 搭載スマートフォン Fx0 について、発売後 1ヵ月ぐらい経ちましたが、最近の記事を集めてみました。

ASCII.jp:文句なしにカッコイイ! Firefoxスマホ「Fx0」の可能性はどんなだ? (1/4)|アスキースマホ総研

(2015 年 01 月 23 日)

au が発表した Firefox OS 搭載スマートフォン「Fx0」(エフエックスゼロ)。半透明の背面パネル、そしてアンテナやパーツの配置も見られることを前提にレイアウトされたデザインがとにかくカッコイイ。

au初のFirefox OSスマホ「Fx0 LGL25」のWebブラウザーはどう?iPhoneやAndroidと比較してみた【レビュー】 - S-MAX(エスマックス) - スマートフォンとモバイルを活用するブログメディア

(2015 年 01 月 23 日)

昨年12月25日にau直営店および公式Webストア「au Online Shop」で発売され、今月6日からはauショップやau取扱店で販売開始されたau初の「Firefox OS」を採用したスマートフォン(スマホ)の「Fx0(型番:...

すべてのアプリがWebアプリ!?auのギーグ向けスマホ「Fx0 LGL25」を使ってFirefox OSアプリの仕組みを紹介【吉川英一の「スマホのちょっと深いとこ」】 - S-MAX(エスマックス) - スマートフォンとモバイルを活用するブログメディア

(2015 年 01 月 25 日)

auが昨年末に発売したFirefox OS搭載ギーグ向けスマホ「Fx0 LGL25」。2015年初にはauショップや家電量販店での販売も開始され、欲しい人には行き渡る体制になってきました。ところでスマートフォンの肝は...

最新のデザイン「Fx0」|革新し続けるデザイナー 吉岡徳仁(1) (1/6)|デザイン|Excite ism(エキサイトイズム)

(2015 年 01 月 26 日)

2014年暮れ、まったく新しい1台のスマートフォンが発表された。それが国内初のFirefox OS搭載端末「Fx0 LGL25」だ。Firefox OSのオー…

可能性は無限大!新たな時代を切り開くFirefox OS搭載スマホ「FX0」

(1015 年 01 月 26 日)

日本の携帯キャリアから初めて発売されるFirefoxスマホ「FX0」。外観のスケルトンボディが強烈なインパクトを与えたようで開発者以外の人たちも気になる存在になっているようです。特に気になってしまう...

 

2015-01-26

Fedora 21 「 Google Chrome 公開鍵がありません」の件 - なんとか ネット。

Fedora 21 にしてから、Chrome の更新時に公開キーがないというアラームに悩まされていましたが、これで解決しました。

ちなみに、上記のサイトで触れられている dnf とは yum からフォークされたプロジェクトで、Fedora プロジェクトでは、次回の 22 のリリースを目標に yum から dnf へ移行するようです。

  1. Changes/ReplaceYumWithDNF - FedoraProject
  2. DNF | Dandified Yum
  3. Everything You Need to Know About the DNF Package Manager - Make Tech Easier
  4. DNF (software) - Wikipedia, the free encyclopedia

 

2015-01-10

2014年に最もシェアが増えたプログラミング言語は「JavaScript」-TIOBE

TIOBE Programming Community Index は、複数の検索エンジンの検索結果から、対象となるプログラミング言語がどれだけ話題になっているかをインデックス化したものです。2014 年にもっともシェアが増えたプログラミング言語は Swift か R になりそうという予想だったのですが、最後に大どんでん返しがありました。

  1. 2014年に最もシェアが増えたプログラミング言語は「JavaScript」-TIOBE | マイナビニュース
  2. TIOBE Software: Tiobe Index

昨年発表された Apple iOS および OS X のアプリケーション開発に用いられる Swift に注目が集まるのは当然ですが、一方の R のランキングが続伸しているのは、昨今のビッグデータに対する興味の高まりを受け、統計処理に関するプログラミング言語の注目度が高まってきていることに因るようです。

首位を勝ち取った Javascript については、クライアントサイドのみならず、サーバーサイドでの開発環境も整いつつあります。Javascript の言語仕様の標準化は、企業間の様々な利害関係が複雑に絡み合って、ユーザーの利益(= ブラウザに依存しない)に直結する方向に最短で進んでいるとはとても言えませんが、そんな中にあっても、もっと便利に使えるようにと有用なライブラリなどの環境がどんどん整ってきています。個人的には、クライアントサイドで規模の大きなアプリケーション開発ができるフレームワークのライブラリに注目しています。特に最近の注目は AngularJS です。先日、ラゾーナ川崎にある丸善をぶらついている時、下記の本がすっと目に入ってきたので、衝動買いしてしまいました。

 

2015-01-09

SPCチャートの作成

SPC, Statistical Process Control (統計的工程管理)とは、製造工程などにおいて安定した品質の製品を作り込むために、品質を左右する重要な 測定値などのパラメータを管理図を用いて管理する活動です。管理図について、教科書的な説明は省略させていただきます。ご興味のある方は、参考サイト [1][2][3] をご覧になってください。

ということで、今回は、SPC で利用する管理図を R で作成してみます。一言で管理図といってもいろいろな種類がありますが、Xbar-R 管理図を作成するサンプルを紹介します。Xbar は平均(MEAN)、R は範囲(RANGE) を意味します。具体的には、製造工程のロットについて、ある測定を何点か実施し、その平均値と範囲(最大値と最小値の差)をロットの処理順にプロットするチャートになります。

ここでは、平均と範囲のトレンドを、R の plot を利用してひとつのプロットにまとめてみました。x 軸には、処理順にロット番号(LOT ID)、y 軸については、平均と範囲についてそれぞれ左右の二軸を使います。plot には二軸に対応した二つのデータ群を自動的に書き分けるような機能はありませんので、プロットを重ね合わせることによって二軸のプロットを実現しています。

なお、それぞれの軸の目盛の付け方には改善の余地があります。汎用的な目盛処理を加えようとすると結構手間が掛かるように感じたので、最大値と最小値のみを目盛に表示するに留めました。

今回も、ファイル選択ダイアログを加えました。例に使用したデータは、sample_spc.csv.zip からダウンロードできるようにしてあります。ご興味があれば、展開してご利用下さい。

require("tcltk")

###############################################################################
# spc.XbarR
###############################################################################
spc.XbarR <- function(tbl, x.col = "LOTID", y.col, y2.col) {
  gTitle <- "Xbar-R chart sample"
  
  # spce to adjust vertical position of y axis label
  pad.label <- "                                       "
  
  # adjust right margin for y2 axis label
  par(oma = c(0, 0, 0, 2))

  # MEAN ######################################################################
  y_max <- max(tbl[, y.col])
  y_min <- min(tbl[, y.col])
  y_min0 <- 2 * y_min - y_max

  plot(c(1, nrow(tbl)), c(y_min0, y_max),
       type = "n", xaxt = "n",  yaxt = "n",
       xlab = "LOT ID", ylab = "",
       main = gTitle, cex.main = 1)
  
  y.label <- paste(pad.label, "MEAN")
  mtext(y.label, side = 2, line = 2)
  axis(2, c(y_min, y_max), c(y_min, y_max))
  points(1:nrow(tbl), tbl[, y.col], type='o', pch = 15, cex = 1, lty = 1, col = "blue")
  
  # enable plot overlay
  par(new = TRUE)
  
  # RANGE #####################################################################
  y2_max <- max(tbl[, y2.col])
  y2_min <- 0
  y2_max0 <- 2 * y2_max

  plot(c(1, nrow(tbl)), c(y2_min, y2_max0),
       type = "n", xaxt = "n", yaxt = "n", axes = FALSE,
       xlab = "", ylab = "",
       main = "", cex.main = 1)
  
  y2.label <- paste("RANGE", pad.label)
  mtext(y2.label, side = 4, line = 2)
  axis(4, c(y2_min, y2_max), c(y2_min, y2_max))
  points(1:nrow(tbl), tbl[, y2.col], type='o', pch = 1, cex = 1, lty = 2, col = "red")

  # X-AXIS ####################################################################
  axis(1, 1:nrow(tbl), tbl[, x.col], las = 2, cex.axis = 0.75)
  
}

###############################################################################
# open.png
###############################################################################
open.png <- function(img.name, pic.width = 640, pic.height = 400) {
  png(filename = img.name, width = pic.width, height = pic.height,
      units = "px", pointsize = 14, bg = "white", res = NA)
}

###############################################################################
# MAIN
###############################################################################

# READ CSV DATA
file.name <-tclvalue(tkgetOpenFile(filetypes="{{CSV} {.csv}}", title = "Open CSV file"))
tbl.data <- read.csv(file.name, header = T, as.is = T)

# first column is always LOTID
# rest of columns are measurement data
n.col <- ncol(tbl.data)
list.meas <- c(2:n.col)

# calculation for mean and range
for (r in 1:nrow(tbl.data)) {
  tbl.data[r, "Xbar"] <- mean(as.numeric(tbl.data[r, list.meas]))
  tbl.data[r, "R"] <- max(as.numeric(tbl.data[r, list.meas])) - min(as.numeric(tbl.data[r, list.meas]))
}

# generate Xbar-R chart
spc.XbarR(tbl.data, "LOTID", "Xbar", "R")

# generate PNG FILE
open.png("sample_spc.png", 1000, 400)
spc.XbarR(tbl.data, "LOTID", "Xbar", "R")
dev.off()

# ---
# END PROGRAM

Fedora での実行例です。

$ R

R version 3.1.2 (2014-10-31) -- "Pumpkin Helmet"
...
(省略)
...
 'q()' と入力すれば R を終了します。 

> source("spc.R")
 要求されたパッケージ tcltk をロード中です 
> 

スクリプトを実行するとファイル選択ダイアログが表示されます。

画面に表示される Xbar-R チャートです。管理図というと、規格値 (LSL, USL)、管理限界値 (LCL, UCL)、さらに工程能力指数 (Cp, Cpk) を書き加えておくと実用的なのですが、作り込みに時間がかかるので、今回は簡単なサンプルということで省略しています。

カレントディレクトリに PNG 形式で保存された Xbar-R チャートです。今回は、横軸の LOT ID が識別できるように横幅を長くして出力しています。

参考サイト

  1. 実践! IE:現場視点の品質管理(14):品質管理に必須の統計的手法「X-R管理図」「P管理図」の作り方 (1/3) - MONOist(モノイスト)
  2. IBM Knowledge Center - 統計的工程管理
  3. JIS Z 9021:1998 シューハート管理図

 

2015-01-05

確率プロットの作成

R によるグラフ作成の復習の第三弾の今回は、確率プロットです。以前の記事は下記の通りです。

今回も、ファイル選択ダイアログを加えました。例に使用したデータはボックスプロットで使用したデータと同じで、sample_box.csv.zip からダウンロードできるようにしてあります。ご興味があれば、展開してご利用下さい。

require("tcltk")

###############################################################################
# chart.cdf
###############################################################################
chart.cdf <- function(tbl, x.val = "RAW_VALUE", col.by = "condition",
                      gTitle = "", x.label = "measured data") {
  x <- tbl[, x.val]
  x <- x[!is.na(x)]
  n <- length(x)
  x <- sort(x)
  y <- (1:n - 0.375) / (n + 0.25)
  
  probs <- c(0.001, 0.01, 0.1, 1, 5, 10, 20, 30, 40, 50,
             60, 70, 80, 90, 95, 99, 99.9, 99.99, 99.999) / 100
  m <-  length(probs)
  
  x_min <- x[1]
  x_max <- x[n]
  x_pad <- (x_max - x_min) * 0.4
  
  y_min <- qnorm(probs[1])
  y_max <- qnorm(probs[m])
  y_stp <- (y_max - y_min) * 0.1
  
  plot(c(x_min, x_max + x_pad), c(y_min, y_max),
       type = "n", yaxt = "n",
       xlab = x.label, ylab = "Cumulative Percent",
       main = gTitle, cex.main = 1)
  axis(2, qnorm(probs), probs * 100)
  abline(h = qnorm(probs), lty = 3, col = "#C0C0C0")
  abline(h = 0, lty = 1, col = "#808080")
  
  list.by <- sort(unique(tbl[, col.by]))
  k <- length(list.by)
  for (i in 1:k) {
    val.by <- list.by[i]
    x <- tbl[tbl[, col.by] == val.by, x.val]
    x <- x[!is.na(x)]
    n <- length(x)
    x <- sort(x)
    y <- (1:n - 0.375) / (n + 0.25)
    
    total <- length(x)
    x.median <- median(x)
    legend_label <- paste(val.by, ':', total, "/", x.median)
    
    points(x, qnorm(y), type='o', col = i, pch = i, cex = 0.7)
    
    legend_x <- x_max + x_pad * 0.05
    legend_y <- y_max - y_stp * (i - 1)
    legend_lty = 1
    legend(legend_x, legend_y, legend_label, col = i,
           lty = legend_lty, pch = i, ncol = 1, cex = 0.7, box.lty = 0)
  }
}

###############################################################################
# open.png
###############################################################################
open.png <- function(img.name, pic.width = 640, pic.height = 400) {
  png(filename = img.name, width = pic.width, height = pic.height,
      units = "px", pointsize = 14, bg = "white", res = NA)
}

###############################################################################
# MAIN
###############################################################################

# READ CSV DATA
file.name <- tclvalue(tkgetOpenFile(filetypes = "{{CSV} {.csv}}", title = "Open CSV file"))
tbl.data <- read.csv(file.name, header = T, as.is = T)

# generate CDF PLOT
head.y <- names(tbl.data)[1]
head.x <- names(tbl.data)[2]
title.box <- paste("SAMPLE (n = ", length(tbl.data[, head.x]), ")", sep = "")
label.x <- "Measurement"
chart.cdf(tbl.data, head.x, head.y, title.box, label.x)

# generate PNG FILE
open.png("sample_cdf.png")
chart.cdf(tbl.data, head.x, head.y, title.box, label.x)
dev.off()

# ---
# END PROGRAM

Fedora での実行例です。

$ R

R version 3.1.2 (2014-10-31) -- "Pumpkin Helmet"
...
(省略)
...
 'q()' と入力すれば R を終了します。 

> source("cdf.R")
 要求されたパッケージ tcltk をロード中です 
> 

スクリプトを実行するとファイル選択ダイアログが表示されます。

画面に表示される確率プロットです。凡例には、データ数とメディアンを表示しています。

カレントディレクトリに PNG 形式で保存された確率プロットです。

 

2015-01-04

ボックスプロットの作成

R によるグラフ作成の復習の第二弾の今回は、ボックスプロットです。以前の記事は下記の通りです。

今回も、ファイル選択ダイアログを加えました。例に使用したデータは sample_box.csv.zip からダウンロードできるようにしてあります。ご興味があれば、展開してご利用下さい。

require("tcltk")

###############################################################################
# chart.boxplot
###############################################################################
chart.boxplot <- function(tbl, x.val, y.val, gTitle = "", x.label = "", y.label = "") {
  tmp <- data.frame(x = tbl[, x.val], y = tbl[, y.val])
  y_max <- max(tmp$y, na.rm = TRUE)
  y_min <- min(tmp$y, na.rm = TRUE)
  y.limit <- c(y_min, y_max)
  
  boxplot(y ~ x, data = tmp, ylim = y.limit,
          main = gTitle, xlab = x.label, ylab =y.label,
          col = "LightBlue", cex.main = 1, outcol = "Orchid")
}

###############################################################################
# open.png
###############################################################################
open.png <- function(img.name, pic.width = 640, pic.height = 400) {
  png(filename = img.name, width = pic.width, height = pic.height,
      units = "px", pointsize = 14, bg = "white", res = NA)
}

###############################################################################
# MAIN
###############################################################################

# READ CSV DATA
file.name <-tclvalue(tkgetOpenFile(filetypes="{{CSV} {.csv}}", title="Open CSV file"))
tbl.data <- read.csv(file.name, header = T, as.is = T)

# generate BOXPLOT
head.x <- names(tbl.data)[1]
head.y <- names(tbl.data)[2]
title.box <- paste("SAMPLE (n = ", length(tbl.data[, head.x]), ")", sep = "")
label.x <- "Condition"
label.y <- "Measurement"
chart.boxplot(tbl.data, head.x, head.y, title.box, label.x, label.y)

# generate PNG FILE
open.png("sample_boxplot.png")
chart.boxplot(tbl.data, head.x, head.y, title.box, label.x, label.y)
dev.off()

# ---
# END PROGRAM

Fedora での実行例です。

$ R

R version 3.1.2 (2014-10-31) -- "Pumpkin Helmet"
...
(省略)
...
 'q()' と入力すれば R を終了します。 

> source("boxplot.R")
 要求されたパッケージ tcltk をロード中です 
> 

スクリプトを実行するとファイル選択ダイアログが表示されます。

画面に表示されるボックスプロットです。

カレントディレクトリに PNG 形式で保存されたボックスプロットです。

 

2015-01-03

ヒストグラムの作成

2015 年は、データ解析手段として R をとことん使いこなさなければならない年になりそうです。いくつか頻繁に使うコードについて整理をしておく必要がありそうですので、以前本ブログで紹介したコードについて再整理して再び紹介します。今回はヒストグラムです。以前の記事は下記の通りです。

今回は、ファイル選択ダイアログを加えました。例に使用したデータは sample_hist.csv.zip からダウンロードできるようにしてあります。ご興味があれば、展開してご利用下さい。

require("tcltk")
require("KernSmooth")

###############################################################################
# chart.hist
###############################################################################
chart.hist <- function(tbl, x.val, g.title = "", x.label = "data") {
  x <- sort(tbl[, x.val])
  x.max <- max(x, na.rm = TRUE)
  x.min <- min(x, na.rm = TRUE)
  x.limit <- c(x.min, x.max)

  h <- try(dpih(x))
  if (!is.numeric(h)) {
    h <- 10^round(log(range(x)[2] - range(x)[1]))
  }
  bins <- seq(x.min - h, x.max + h, by = h)

  hist(x, breaks = bins, freq = FALSE,
       main = g.title, xlab = x.label, xlim = x.limit,
       col = "LightBlue", cex.main = 1, family = "mono")
  
  points(x, dnorm(x, mean(x), sd(x), log = FALSE),
         type='l', col = "Magenta", lwd = 1)
  points(density(x), type = 'l', col = "MidnightBlue", lwd = 1)
}

###############################################################################
# open.png
###############################################################################
open.png <- function(imgName, picWidth = 640, picHeight = 400) {
  png(filename = imgName, width = picWidth, height = picHeight, units = "px",
      pointsize = 14, bg = "white", res = NA)
}

###############################################################################
# MAIN
###############################################################################

# READ CSV DATA
file.name<-tclvalue(tkgetOpenFile())
tbl.data <- read.csv(file.name, header = T, as.is = T)

# generate HISTOGRAM
head.x <- names(tbl.data)[1]
title.hist <- paste("SAMPLE (n = ", length(tbl.data[, head.x]), ")", sep = "")
label.x <- "Measurement"
chart.hist(tbl.data, head.x, title.hist, label.x)

# generate PNG FILE
open.png("sample_hist.png")
chart.hist(tbl.data, head.x, title.hist, label.x)
dev.off()

# ---
# END PROGRAM

Fedora での実行例です。

$ R

R version 3.1.2 (2014-10-31) -- "Pumpkin Helmet"
...
(省略)
...
 'q()' と入力すれば R を終了します。 

> source("histogram.R")
 要求されたパッケージ tcltk をロード中です 
 要求されたパッケージ KernSmooth をロード中です 
KernSmooth 2.23 loaded
Copyright M. P. Wand 1997-2009
>

スクリプトを実行するとファイル選択ダイアログが表示されます。

画面に表示されるヒストグラムです。

カレントディレクトリに PNG 形式で保存されたヒストグラムです。

 

2015-01-01

「七つの会議」を読んで

2013 年に NHK でドラマ化された作品ですが、ドラマの方は見ていません。そう言えば半沢直樹シリーズのドラマ化が話題となりましたが、こちらもドラマの方は見ていません。しかし、ドラマ人気の影響で書店に多くの池井戸作品が並ぶようになったので、「オレたちバブル入行組 」を読んでみたらその面白さの虜に。以来すっかり池井戸作品のファンになってしまっています。

さてこの「七つの会議」は、中堅電機メーカーで起こった不祥事に巻き込まれていく社員たちを描く群像劇です。年末年始の休暇で、大掃除もせずに久しぶりに読みかえしたところ、初読の時とは違う感想をいろいろ持ちましたので、ブログにまとめてみました。

タイトルの 七つの〜 はキリスト教世界の「七つの大罪/罪源」である[傲慢、物欲(貪欲)、ねたみ(嫉妬)、憤怒、貪食、色欲(肉欲)、怠惰]を意識しているように感じられます。ストーリは、最終話「最終議案」を含む八話で構成されており、(初読時は)最初の数話を読んだだけでは、問題の核心に触れることができず、オムニバス形式の作品かと思ってしまいました。しかし、読み進めるうちに、そうではなく、各話が関連していることに気が付き、そしてどんどんと問題の核心に引き込まれてしまいました。

超あらすじ

大手総合電機の雄であるソニックの子会社である東京建電で、椅子に使われているねじの強度不足によるクレームが発生し、このことをきっかけに、同じねじメーカーで使われているほとんどが製品規格を満たしていない、強度不足のねじであることが発覚します。このねじの不良を巡る社内隠蔽の動き、内部告発の顛末が描かれています。

ねじの強度とコストインパクト

読んでいて気になったことが一点あります。廉価な強度不足のねじを使うことが、はたして商品である椅子にどれだけのコストインパクトがあるのか、という点です。作中のコンペではコストが全てであるようになっていたので、そうであれば、ねじ強度の偽装でどれだけ商品の価格を下げることができたのか、読者がなるほどと納得できるような話の組み立てになっていれば良かったように思います。

コンペによる一社選定は現実的か?

そもそも大口の重要なコンペであれば、採算度外視とまでいかなくとも戦略的な価格設定で参入を果し、量産効果による製造コストと原材料あるいは部品調達コストの削減を進めて設定期間内に黒字化を目指すというのが、私の素人考えです。またコンペはするが、二社購買あるいは複数社購買による購入リスク低減と各社購入比率の管理をするのが、選定側の一般的な調達戦略のように思います。自分のエンジニアとしての経験では、実験用の新規部材の購入ですら、最終的な採用を見越して、二社購買の要求が常に購買部門からあったからです。

小説ですから、話の単純化はもちろん必要なのでしょう。

品質の砦 ─ 品質保証

作中では、親会社であるソニック、子会社の東京建電、そして取引先の会社と利害関係は単純で理解し易い構成になっています。東京建電社内は、人事部、経理部、商品企画部なども出てきますが、作中ではメインプレーヤが営業部と製造部の二部門に単純化されており、営業部門が仕入先を選定する役割を担っています。

その営業部門の担当課長とねじの取引先で偽装が企てられるのですが、それを何年も隠蔽し通せるものでしょうか。実際、収益率の変化から他の営業課員によってコストダウンのからくりが暴かれることになるのですが、品質保証部門に身を置く者として、ものづくりの現場から離れたところで展開される話にやや違和感をおぼえました。

ものづくりの現場では、納入している製品の性能や安全性を保証するために、ある頻度の抜き取りで信頼性試験を実施するはずです。また、ねじの強度が安全性や耐久性に関わる重要な因子の一つだと認識されていれば、納入されたねじの受け入れ検査でも、ある頻度の抜き取りで強度試験を実施するはずです。いずれにしても、ねじの強度のような単純な性能不足を長年に亘って隠蔽し続けることは不可能ではないかと思うからです。

また、この東京建電には半導体関連のセクションがあるということが第一話で触れられているので、これは半導体産業に限ったことではないのですが、製品設計や製造のプロセスでは変更管理のしくみが確立されているはずです。営業部門が仕入先を選定する役割を担っているとしても、仕入先変更は社内の変更管理プロセスに従って実施され、どうしてもそこで客観的な評価が入ってくるため、不正を隠し通すことは大変難しくなります。

しかし、コストに直接寄与しないしくみというものは形骸化しやすく、不正な変更が隠蔽されつづけることが可能になってしまう場合もあります。

年商一千億円規模の東京建電とはいえ、今どきのものづくりの企業であれば ISO 9001 の認証は取得しているでしょうから、こういった品質に関わる偽装が明らかになり、その企業が謝罪会見を開く時、社長と共に会見に出席するのは、品質管理責任者 (Quality Management Representative) と呼ばれる、品質保証(品質管理)部長か、担当役員になるでしょう。

品質保証の立場でものを言ってしまいましたが、こういった現実を小説に持ち込んでしまっては、エンターテインメント性が損なわれてしまうかもしれません。

もうひとつの砦 ─ 内部監査

内部告発は、それこそ正義を貫く最後の手段です。内部告発に踏み切る前に、内部監査に判断を委ねることもできるはずです。内部監査とは組織体の内部の者による監査のことを言います。組織体のガバナンス・プロセスの有効性や財務管理状態を監査する内部統制の視点による内部監査の他に、品質や環境、安全衛生マネジメントを監査する内部監査もあります。しかし、不正を内部監査で暴き是正させることが、機能としては可能であるとは言え、いざ実行に移すには、それなりの覚悟が必要になります。

都合の悪い事実の揉み消しと戦う内部監査

「七つの会議」の感想とはズレてしまいますが、不正を正した内部監査の事例を紹介します。

事例は、品質の内部監査です。内部監査員は、部門横断的に従業員で組織され、主に係長、主任クラスの役職者で構成されています。製造プロセスの内部監査において、ある製品の納入仕様書に記載されている出荷検査項目のひとつである検査試験 A が、試験を実施していないにもかかわらず、さも試験をしたかのように架空の数値を記載して何年も出荷され続けていたという事実が発覚しました。こうなった理由は、過去に担当検査員が異動したことにより、この試験を実施できなくなってしまったということなのですが、深刻なことに、担当部署の管理職(課長)をはじめ、その上位職者もこの不正を認識していたということでした。当然、内部監査員の判断は「major な不適合」でした。

内部監査報告書は、被監査部門の部門長の承認の上で確定します。問題は、被監査部門である品質管理部 (QC) の部長を、本部長である品質管理責任者が兼務していたことです。この時の内部監査チームのリーダーは品質保証部 (QA) の係長で、社内事情に通じていたため、不適合の事実が品質管理責任者に揉み消されることを心配しました。職制では立場が弱い内部監査員の指摘が、そのまま監査報告書に記載されて確定するとは限らないのです。その日の夜に主任内部監査員である品質マネジメントシステム課 (QMS) の課長と一緒に、部門長である私に相談にきましたので、もみ消しを阻止することを請け負いました。翌朝の本部の全体朝礼において、事前のネゴ無しに、本部長の横でしゃあしゃあと昨日の内部監査で上がった不適合候補を周知し、速やかに是正に取り組むことを指示したのでした。この不意の周知行動に、本部長の怒りを買ったのは当然ですが、もう手遅れです。不適合の事実は、その後、業務報告会やマネジメントレビューの場で、QMS 課長から繰り返し報告されることになりました。

この不適合の是正処置は、結果的には、品質保証部 (QA) が当該納入仕様書から検査試験 A を外すことを顧客の合意を得て改定するという、なんとも情け無い形でクローズしました。属人化していた特定の検査試験に対する人的リソースの割り当ての仕方の改善や、絶えず変化する検査試験への要求に対応できる組織的な人員計画の改善などに確実に着手できるような対策が品質管理部 (QC) で講じられたとはとても言えませんでした。

また、お客様目線に立った行動が取れておらず、どうしても内向きになってしまうところが気に入りませんが、事業が B2B で、人命に影響するような製品を販売していないため、顧客重視のスローガンばかりの中途半端な行動になってしまうことは、致し方がない事なのかもしれません

しかし、品質の内部監査が、たとえ品質管理部 (QC) のような足元の組織においても正常に機能して、不正があれば(それなりに)正すことができるということを社長にアピールできたことはひとつの成果と言えます。

まとめ

長い感想文になってしまいましたが、「品質 Quality」とは顧客満足の実現であると考えている自分にとって、アプローチは違えど、池井戸氏が描く世界には共感できる部分がとても多いです。半沢直樹のシリーズでもそうですが、顧客のことを考えて仕事をする、それが池井戸氏の一貫した考えのように感じとれます。

土曜ドラマ 「七つの会議」 | NHKドラマ のあらすじを読むと、ドラマの主役は東山紀之扮する原島課長のようです。しかし、原作では、万年係長である八角民夫が主役のように思いました。しかしこの主役は決して多くを語らず、関係する周りの人間がいろいろと考え、苦悩します。

最後に、印象に残った村西副社長の言葉を引用します。

いまはっきりとかる。あのとき、父がいった言葉は、ビジネスに携る者が決して忘れてはならない金言なのだと。

── 客を大事にせん商売は滅びる。

参考サイト

  1. もの作りのための機械設計工学
  2. 三菱リコール隠し - Wikipedia
  3. 失敗事例 > 三菱自動車のリコール隠し
  4. ロドデノール - Wikipedia

 

2014-12-30

【備忘録】XMind と Fedora 21

XMindは、マインドマップを作成できるソフトウェアです。

マインドマップを用いることで、物事を視覚的・構造的に整理しやすくなります。普段の業務の中に出てくるアイデアや発想、打ち合わせの内容などをマインドマップに書きとめておくことで、それぞれの物事の関係が非常に分かりやすくなります。こういった PC 上のツールがなければ、紙に書き出せば良いのですが、一度でも PC で利用できるツールを使ってしまうと、もう紙には戻れません。

マインドマップを扱うソフトウェアには、FreeMind という GPL の下で配布されるツールがあり、Fedora で利用できるのですが、個人的にはクローズドソースである XMind の方が機能的に使い易いと思っているので、こちらを使っています。XMind には無料版の XMind と、有料版の XMind Plus、XMind Pro が提供されています。ぞれぞれの機能の違いは下記にまとめられています。

alien による deb ⇒ RPM 変換

ここでは、無料版を Fedora で利用する場合について紹介します。Linux 用パッケージは以下のサイトから入手します。

Linux 版は残念ながら Debian/Ubuntu の deb パッケージのみ提供されていますが、これを alien で RPM へ変換することにします。以前、本ブログの過去記事「【備忘録】マインドマップツール XMind と alien --- rpm, deb などの変換ツール」で、alien を使った変換方法を紹介していますので、これと同じことをします。

# alien --to-rpm --scripts xmind-jp-linux-3.5.1.201411201906_amd64.deb
xmind-3.5.1-2.x86_64.rpm generated

これを、yum localinstall でインストールしようとしたところ、エラーになってしまいました。

# yum localinstall xmind-3.5.1-2.x86_64.rpm
読み込んだプラグイン:langpacks
xmind-3.5.1-2.x86_64.rpm を調べています: xmind-3.5.1-2.x86_64
xmind-3.5.1-2.x86_64.rpm をインストール済みとして設定しています
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ xmind.x86_64 0:3.5.1-2 を インストール
--> 依存性解決を終了しました。
adobe-linux-x86_64                                          |  951 B  00:00     
...
(省略)
...
updates/21/x86_64/pkgtags                                   | 1.3 MB  00:01     

依存性を解決しました

================================================================================
 Package      アーキテクチャー
                            バージョン       リポジトリー                  容量
================================================================================
インストール中:
 xmind        x86_64        3.5.1-2          /xmind-3.5.1-2.x86_64        109 M

トランザクションの要約
================================================================================
インストール  1 パッケージ

合計容量: 109 M
インストール容量: 109 M
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test


Transaction check error:
  ファイル /usr/bin (パッケージ xmind-3.5.1-2.x86_64 から) は、パッケージ filesystem-3.2-28.fc21.x86_64 からのファイルと競合しています。
  ファイル /usr/lib (パッケージ xmind-3.5.1-2.x86_64 から) は、パッケージ filesystem-3.2-28.fc21.x86_64 からのファイルと競合しています。

エラーの要約
-------------

#

自動変換した XMind のSPEC ファイルで /usr/bin/usr/lib の両ディレクトリを定義しているが故の競合であると予想されます。あまり害が無いので rpm コマンドで強制的にインストールするのもアリですが、ここでは SPEC ファイルを編集して yum でエラーが出ないパッケージを作ることにしました。

無料でダウンロードできる XMind は、「デュアルライセンスについて XMind」を読む限り、RPM パッケージでの再配布ができそうですが、確認が不十分ですので、現在のところ、RPM パッケージの作成方法を以下に紹介するに留めます。

SPEC ファイルの編集

alien には、パッケージ変換に使用するファイルを一時ディレクトリに保存してくれる --generate というオプションがあります。このオプションを使って、以下のようにして SPEC ファイルを含むビルドに必要なファイルを取得します。

$ alien --to-rpm --scripts --generate xmind-jp-linux-3.5.1.201411201906_amd64.deb
Warning: alien is not running as root!
Warning: Ownerships of files in the generated packages will probably be wrong.
Directory xmind-3.5.1 prepared.
$ ls xmind-3.5.1
etc  usr  xmind-3.5.1-2.spec
$ 

ディレクトリ xmind-3.5.1 の中にある xmind-3.5.1-2.spec を編集します。と言っても下記の %file セクションの数箇所(緑の行)をコメントアウトするだけです。

Buildroot: /home/bitwalk/ダウンロード/xmind-3.5.1
Name: xmind
Version: 3.5.1
Release: 2
Summary: Professional & Powerful Mind Mapping Software
License: see /usr/share/doc/xmind/copyright
Distribution: Debian
Group: Converted/non-free/editors
...
(省略)
...
(Converted from a deb package by alien version 8.90.)

%files
%dir "/etc/"
%config "/etc/XMind.ini"
#dir "/usr/"
#dir "/usr/bin/"
"/usr/bin/XMind"
#dir "/usr/lib/"
%dir "/usr/lib/xmind/"
"/usr/lib/xmind/.eclipseproduct"
"/usr/lib/xmind/about.html"
%dir "/usr/lib/xmind/about_files/"
"/usr/lib/xmind/about_files/about_cairo.html"
"/usr/lib/xmind/about_files/mpl-v11.txt"
"/usr/lib/xmind/about_files/pixman-licenses.txt"
"/usr/lib/xmind/artifacts.xml"

RPM パッケージのビルド

編集した xmind-3.5.1-2.spec$HOME/rpmbuild/SPECS へ保存し、ディレクトリ xmind-3.5.1 を、xmind-3.5.1-2.x86_64 に名前を変えて $HOME/rpmbuild/BUILDROOT へコピーします。$HOME/rpmbuild/SPECS へカレントディレクトリを移し、下記のようにして RPM パッケージをビルドします。

$ rpmbuild -ba xmind-3.5.1-2.spec
ファイルの処理中: xmind-3.5.1-2.x86_64
...
(省略)
...
パッケージに含まれないファイルの検査中: /usr/lib/rpm/check-files /home/bitwalk/rpmbuild/BUILDROOT/xmind-3.5.1-2.x86_64
警告: インストール済み(ただしパッケージに含まれない)ファイルが見つかりました:
   /xmind-3.5.1-2.spec
書き込み完了: /home/bitwalk/rpmbuild/SRPMS/xmind-3.5.1-2.src.rpm
書き込み完了: ../xmind-3.5.1-2.x86_64.rpm
実行中(%clean): /bin/sh -e /var/tmp/rpm-tmp.noBYpc
+ umask 022
+ cd /home/bitwalk/rpmbuild/BUILD
+ /usr/bin/rm -rf /home/bitwalk/rpmbuild/BUILDROOT/xmind-3.5.1-2.x86_64
+ exit 0
$ 

この場合、xmind-3.5.1-2.x86_64.rpm は、$HOME/rpmbuild/ に出力されます。インストールでは下記のように警告のようなものが出ますが、他パッケージと競合せずにインストールができます。

# yum localinstall xmind-3.5.1-2.x86_64.rpm
読み込んだプラグイン:langpacks
xmind-3.5.1-2.x86_64.rpm を調べています: xmind-3.5.1-2.x86_64
xmind-3.5.1-2.x86_64.rpm をインストール済みとして設定しています
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ xmind.x86_64 0:3.5.1-2 を インストール
--> 依存性解決を終了しました。

依存性を解決しました

================================================================================
 Package      アーキテクチャー
                            バージョン       リポジトリー                  容量
================================================================================
インストール中:
 xmind        x86_64        3.5.1-2          /xmind-3.5.1-2.x86_64        109 M

トランザクションの要約
================================================================================
インストール  1 パッケージ

合計容量: 109 M
インストール容量: 109 M
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  インストール中          : xmind-3.5.1-2.x86_64                            1/1 
Unknown media type in type 'all/all'
Unknown media type in type 'all/allfiles'
Unknown media type in type 'uri/mms'
Unknown media type in type 'uri/mmst'
Unknown media type in type 'uri/mmsu'
Unknown media type in type 'uri/pnm'
Unknown media type in type 'uri/rtspt'
Unknown media type in type 'uri/rtspu'
  検証中                  : xmind-3.5.1-2.x86_64                            1/1 

インストール:
  xmind.x86_64 0:3.5.1-2                                                        

完了しました!
# 

デスクトップ環境が MATE の場合は、メニューには「アプリケーション」→「オフィス」→「XMind」と登録されています。GNOME 3 の場合は、下記のようにアイコンが加えられます。

起動中の画面です。

以下のように無事起動しました。なお、デスクトップ環境は MATE を使っています。

ちょっとしたアイデアを整理したり、ブレインストーミングに使ったり、なかなか重宝するツールです。ロジックツリーなどマインドマップ以外のレイアウトも利用できるので、仕事の整理にも活用しています。下記は自分の強みをまとめているものです。使用例として紹介しておきます。