[Java][機器學習]用決策樹分類演算法對Iris花資料集進行處理
Iris Data Set是很經典的一個數據集,在很多地方都能看到,一般用於教學分類演算法。這個資料集在UCI Machine Learning Repository裡可以找到(還是下載量排第一的資料喲)。這個資料集裡面,每個資料都包含4個值(sepal length,sepan width,petal length,petal width)以及其種類。而分類演算法的目標,就是根據4個值來把花的種類確定下來。
分類的大概原理就是利用熵的變化來判斷哪個屬性最適合分類(這個書上都有詳細的解釋)。寫這個演算法花了我挺多的時間,有點出乎我的意料。整套程式碼共850行,這裡面還包括將資料從我的資料庫取出來以及將資料輸出到excel檔案的程式碼。寫完之後想想,還是有很多地方寫的不夠緊湊,以後改進吧。
如前所說,我事先把資料集儲存在SQL資料庫裡面,然後有些結果會輸出到桌面上的”text.xls”檔案裡面。下面上程式碼。整個工程共8個類,分別為IrisData,IrisInfoGet,IrisNode,Hunt,Estimate,ExcelPrint,DataProperty,test。另外還需要兩個外部類,分別為sqljdbc.jar(負責SQL連線)以及jxl.jar(EXCEL連線)
test 程式的入口
IrisData 資料的基本結構
IrisInfoGet 負責從SQL中提取資料並轉化成IrisData陣列的形式。
IrisNode 負責用訓練集生成決策樹。
Hunt 負責尋找當前決策樹節點最適合分類的屬性,是決策樹演算法的關鍵組成部分。
Estimate 負責用檢測集來檢測決策樹的效能。
ExcelPrint 將IrisData陣列輸出到excel檔案裡面。
DataProperty 是個輔助類,用於計算陣列的熵等。
1.IrisData
public class IrisData {
public double SL,SW,PL,PW ; //Sepal Length/Width, Petal Length/Width
public int Type; //Iris-setosa:0 Iris-versicolor:1 Iris-virginica:2
public int tempType ;
public int SetNum ; //IrisSet的編號
public IrisData(){
this.SL=-1 ; //Sepal Length
this.SW=-1 ; //Sepal Width
this.PL=-1 ; //Petal Length
this.PW=-1 ; //Petal Width
this.Type=-1 ; //The type of the flower
this.tempType=0 ;
this.SetNum=-1 ;
}
public IrisData(double SL,double SW,double PL,double PW,int Type,int SetNum){
this.SL=SL ;
this.SW=SW ;
this.PL=PL ;
this.PW=PW ;
this.Type=Type ;
this.tempType=-1 ; //tempType=-1 means undefined
this.SetNum=SetNum ;
}
}
除了原來就有的SL,SW,PL,PW,Type等值外,還多了SetNum以及tempType。其中SetNum指的是當前資料的序號,在實際應用中沒什麼用,但是tempType很關鍵。由於不知道如何直接將眾多元素分成多類,我採取的方法是先將一種(假定為0號花)分離出來,然後再將1號和2號花分離。那麼這是就需要一個臨時屬性。比如在將0號分離時,0號花的tempType=0,而1,2號花的tempType=1.而在分離1和2時,1號花的tempType=0,2號花的tempType=1.
2.IrisInfoGet
/*import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
*/
import java.sql.* ;
/**
* @function get data from SQL Server as the type of IrisData
* @author multiangle from Southeast University
*/
public class IrisInfoGet {
public IrisData[] dataset ;
public IrisInfoGet(){
ResultSet rs=getResultSet() ;
this.dataset=ResultDeal(rs) ;
}
public static void main(String[] args) throws SQLException{
ResultSet rs=getResultSet();
IrisData[] data=ResultDeal(rs) ;
}
private static ResultSet getResultSet(){
String JDriver="com.microsoft.sqlserver.jdbc.SQLServerDriver";//SQL資料庫引擎
String connectDB="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=multiangle";//資料來源
try{
Class.forName(JDriver);//載入資料庫引擎,返回給定字串名的類
System.out.println("資料庫驅動成功");
}catch(ClassNotFoundException e){ //e.printStackTrace();
System.out.println("載入資料庫引擎失敗");
System.out.println(e);
}
ResultSet rs ;
try{
String user="sa" ;
String password="admin" ;
Connection con=DriverManager.getConnection(connectDB,user,password);
System.out.println("資料庫連線成功");
Statement stmt=con.createStatement() ;
String query="select ROW_NUMBER()over(order by class)as row,* from dbo.[bezdekIris.data]" ;
rs=stmt.executeQuery(query) ;
return rs ;
}catch(SQLException e){
System.out.println(e) ;
System.out.println("資料庫內容讀取失敗");
return null ;
}
}
public static IrisData[] ResultDeal(ResultSet rs){
IrisData[] dataset=new IrisData[150] ;
int num=0 ;
try {
while((num<150)&&(rs.next())){
double SL=Double.parseDouble(rs.getString("SepalLength")) ;
double SW=Double.parseDouble(rs.getString("SepalWidth")) ;
double PL=Double.parseDouble(rs.getString("PetalLength")) ;
double PW=Double.parseDouble(rs.getString("PetalWidth")) ;
int setnum=Integer.parseInt(rs.getString("row")) ;
String name=rs.getString("Class") ;
int type ;
if(name.equals("Iris-setosa")) type=0 ;
else if(name.equals("Iris-versicolor")) type=1 ;
else if(name.equals("Iris-virginica")) type=2 ;
else type=-1 ;
dataset[num++]=new IrisData(SL,SW,PL,PW,type,setnum) ;
//System.out.println(setnum+" "+SL+" "+SW+" "+PL+" "+PW+" "+type) ;
}
System.out.println("ResultSet 解析完畢");
return dataset ;
} catch (SQLException e) {
System.out.println("ResultSet 解析出錯");
System.out.println(e);
return null ;
}
}
}
負責從SQL讀取資料並返回IrisData[]形式。其中的getResultSet()返回的是ResultSet格式,然後由ResultDeal()處理以後返回IrisData[]形式。關於如何從SQL Server讀取資料,我之前的部落格裡有寫(也是極端新手向)
3.IrisNode
/**
* @function the node of IrisTree
* @author multiangle from SoutheastUniversity
*/
public class IrisNode {
//Elements for Node itself
public int deep ; // the deep of the IrisNode tree
public double formerEntropy ; // the entropy of the list belong to the node
public IrisData[] datalist ; // the data list belong to the node
public String tag ; // in order to research the node tree
public int nodeType=-1 ; //nodeType=-1 means it's not leaf node =0 means it belongs to class0(tempType) =1 belongs to class1
public int divideType=-1 ; // the attritube selected to divide the IrisData list
public double valveValue=-1 ; // the corresponding value of the attribute to divide
//Elements for the child for the node
public IrisNode leftChild=null ; // the left child of the node
public IrisNode rightChild=null ; // the right child of the node
public double laterEntropy=-1 ; // the total entropy of the two node after division
public double deltaEntropy=0 ; // the change of entropy between the ahead and after division
//Methods in Node class
public IrisNode(IrisData[] input,int deep,String tag){ //Construction Method
this.tag=tag ;
this.deep=deep ;
this.datalist=input ;
this.formerEntropy=getIrisDataListEntropy(input) ;
this.nodeType=-1 ;
if ((this.deep>5)||(this.datalist.length<2)){
this.leftChild=this.rightChild=null ;
int temp=decideType(this.datalist) ;
if ((temp==0)||(temp==1)) this.nodeType=temp ;
else System.out.println("ERROR:函式decideType輸出值不合法") ;
}else{
Hunt hunt=new Hunt(input) ;
this.divideType=hunt.type ;
this.valveValue=hunt.value_value ;
this.laterEntropy=hunt.min_entropy ;
this.deltaEntropy=this.formerEntropy-this.laterEntropy ;
if ((this.formerEntropy-this.laterEntropy)<0.05){
this.leftChild=this.rightChild=null ; //if deltaEntropy<0.05 or deep>5 no longer continue
int temp=decideType(this.datalist) ;
if ((temp==0)||(temp==1)) this.nodeType=temp ;
else System.out.println("ERROR:函式decideType輸出值不合法") ;
}else{
//System.out.println("tag1") ; //used for debug
IrisData[] leftList=Divide(input,this.divideType,this.valveValue,0) ;
IrisData[] rightList=Divide(input,this.divideType,this.valveValue,1) ;
if ((leftList.length==0)||(rightList.length==0)) {
this.leftChild=this.rightChild=null ;
int temp=decideType(this.datalist) ;
if ((temp==0)||(temp==1)) this.nodeType=temp ;
else System.out.println("ERROR:函式decideType輸出值不合法") ;
}
else{
this.leftChild=new IrisNode(leftList,deep+1,tag+'0') ;
this.rightChild=new IrisNode(rightList,deep+1,tag+'1') ;
}
}
}
}
public static IrisData[] Divide(IrisData[] input,int attribute,double valve,int methodtype){
IrisData[] rs=null ;
//通過attribute value type來將input分成兩部分
if (methodtype==0){ //此處為methodtype=1時的情況,也就是attr value<valve的情況
int num=0 ;
for(int i=0;i<input.length;i++){
double tempvalue=-1 ; //tempvalue初始值為=-1 在複用時要注意一下
switch(attribute){
case 0: {tempvalue=input[i].SL;break;}
case 1: {tempvalue=input[i].SW;break;}
case 2: {tempvalue=input[i].PL;break;}
case 3: {tempvalue=input[i].PW;break;}
default: System.out.println("ERROR:The value of attribute value illegal");
}
if(tempvalue<=valve) num++ ;
}
rs=new IrisData[num] ;
int index=0 ;
for(int i=0;i<input.length;i++){
double tempvalue=-1 ;
switch(attribute){
case 0: {tempvalue=input[i].SL;break;}
case 1: {tempvalue=input[i].SW;break;}
case 2: {tempvalue=input[i].PL;break;}
case 3: {tempvalue=input[i].PW;break;}
}
if (tempvalue<=valve) rs[index++]=input[i] ;
}
return rs ;
}else if(methodtype==1){
int num=0 ;
for(int i=0;i<input.length;i++){
double tempvalue=-1 ; //tempvalue初始值為=-1 在複用時要注意一下
switch(attribute){
case 0: {tempvalue=input[i].SL;break;}
case 1: {tempvalue=input[i].SW;break;}
case 2: {tempvalue=input[i].PL;break;}
case 3: {tempvalue=input[i].PW;break;}
default: System.out.println("ERROR:The value of attribute value illegal");
}
if(tempvalue>valve) num++ ;
}
rs=new IrisData[num] ;
int index=0 ;
for(int i=0;i<input.length;i++){
double tempvalue=-1 ;
switch(attribute){
case 0: {tempvalue=input[i].SL;break;}
case 1: {tempvalue=input[i].SW;break;}
case 2: {tempvalue=input[i].PL;break;}
case 3: {tempvalue=input[i].PW;break;}
}
if (tempvalue>valve) {rs[index++]=input[i] ;}
}
return rs ;
}else System.out.println("ERROR:methodtype value illegal");
return rs ;
}
//------Private Method-----------------------
private static int decideType(IrisData[] input){ //decide which class this node belongs to
int rs=-1 ;
int num0=0,num1=0 ;
for(int i=0;i<input.length;i++){
if (input[i].tempType==0) num0++ ;
if (input[i].tempType==1) num1++ ;
}
if (num0<num1) rs=1 ; //有條件的話可以吧num0=num1時node的歸屬用隨機數來實現
else rs=0 ;
return rs ;
}
private static double getIrisDataListEntropy(IrisData[] input){
DataProperty dp=new DataProperty() ;
double rs_entropy=-1 ;
//通過tempType的值來計算irisdata陣列的熵
//tempType只有3個值,0表示類1,1表示類2,-1表示其他類 一般用於表示異常
int num1=0,num2=0 ;
for(int i=0;i<input.length;i++){
if(input[i].tempType==0) num1++ ;
if(input[i].tempType==1) num2++ ;
}
rs_entropy=dp.getEntropy(num1, num2) ;
return rs_entropy ;
}
}
在IrisNode類的幾個元素裡,Node.deep表示該節點的深度。根節點的深度為0.
datalist表示該節點內的IrisData陣列。
formerEntropy表示分類前的陣列(dtalist)的熵。
tag表示從根節點到當前節點的路徑。
nodeType表示該節點的類。nodeType=-1時表示這是個頁節點。=0或1時表示這是個葉節 點,=0表示這個節點內大部分資料的分類是tempType=0;=1表示大部分節點的tempType=1 .
divideType指最佳的分類屬性,值從0-3,分別表示4個屬性值。
valveValue指最佳屬性的最佳分類值。小於valveValue的分到左子樹,大於valvaValue的分到右子樹。
leftChild,rightChild顧名思義,左子樹和右子樹。
建構函式的結構
if (節點深度>5)且(節點陣列長度小於2) //此時為葉節點
左右子樹為空
判斷葉節點的型別(屬於類0還是類1)
else
尋找最合適的分類屬性以及分類值。(Hunt演算法)
if (分類後熵的變化小於0.05) 則左右字數為空,判斷葉節點型別
else
根據分類屬性以及分類值來劃分左右子樹。
if(左子樹或右子樹長度為0) 則左右子樹為空,判斷葉節點型別
else 以左右子樹再次呼叫建構函式,形成遞迴。
end if
end if
end if
4.Hunt
/**
*@author multiangle from SoutheastUniversity
*@function Hunt Method is used to get the best attribute and the best value
* to divide a node into two parts
*/
public class Hunt {
public double min_entropy ;
public double value_value ;
public int type ;
public Hunt(IrisData[] dataset){
//1. calculate the entropy of initial dataset
//2. find best attritube from 4
double[][] rs=new double[4][2] ;
int mintype=0 ;
double minentropy=2 ;
double valve_value=-1 ;
for(int i=0;i<4;i++){
rs[i]=FindBestValve(preDeal(dataset,i)) ;
if(rs[i][0]<minentropy){
minentropy=rs[i][0] ;
valve_value=rs[i][1] ;
mintype=i ;
}
}
//3. find the best one and output
this.min_entropy=minentropy ;
this.value_value=valve_value ;
this.type=mintype ;
}
private static double[][] preDeal(IrisData[] dataset,int type){ //transfer IrisData[] to int[][] to fit the followign processing
if ((type<4)&&(type>=0)){
double[][] rs=new double[dataset.length][3] ; //3 attributes:Number,Attribute Value,Type
for(int i=0;i<dataset.length;i++){
rs[i][1]=dataset[i].SetNum ;
rs[i][2]=dataset[i].tempType ; //ATTENTION the taken value is tempTyoe!
switch(type){
case 0:{rs[i][0]=dataset[i].SL ;break ;} //0 means sepal length
case 1:{rs[i][0]=dataset[i].SW ;break ;} //1 means sepal width
case 2:{rs[i][0]=dataset[i].PL ;break ;} //2 means petal length
case 3:{rs[i][0]=dataset[i].PW ;break ;} //3 means petal width
}
}
return rs ;
}else {System.out.println("ERROR:type輸入值不正確");return null ;}
}
private static double[] FindBestValve(double[][] input){
//要考慮Type的多值性,最好只有兩個值
double[][] sorted=QuickSort(input,0,input.length-1) ; //1st step:sort the input array
//接下來應該要在不同值區間內迴圈,挑一個熵值最小的。
double min_entropy=2 ;
double valve_value=-1 ;
for(int i=0;i<sorted.length-1;i++){
// calculate the entropy of the division whose valve is between i and i+1
if (sorted[i][0]!=sorted[i+1][0]){ //避免在兩個相同值之間分析的情況
double temp_entropy=CalculateEntropy(sorted,i) ;
if (temp_entropy<min_entropy){
min_entropy=temp_entropy ;
valve_value=(sorted[i][0]+sorted[i+1][0])/2 ;
}
}
}
double[] rs=new double[2] ;
rs[0]=min_entropy ;
rs[1]=valve_value ;
return rs ;
}
private static double CalculateEntropy(double[][] sorted,int i) { //can only deal with the data which have only two classes
DataProperty dp=new DataProperty() ; //initialization of dataproperty
double rs_entropy=-1 ;
int num1=0 ;
int num2=0 ;
for(int x=0;x<i+1;x++){
if(sorted[x][2]==0) num1++ ;
else if(sorted[x][2]==1) num2++ ;
else System.out.println("ERROR from CalculateEntropy: the value of tempType of a item is -1");
}
double entropy1=dp.getEntropy(num1,num2) ;
int tnum1=num1+num2 ; //total number of the former sequence
num1=0 ;
num2=0 ;
for(int x=i+1;x<sorted.length;x++){
if(sorted[x][2]==0) num1++ ;
else if(sorted[x][2]==1) num2++ ;
else System.out.println("ERROR from CalculateEntropy: the value of tempType of a item is -1");
}
double entropy2=dp.getEntropy(num1,num2) ;
int tnum2=num1+num2 ;
rs_entropy=(entropy1*tnum1+entropy2*tnum2)/(tnum1+tnum2) ;
return rs_entropy ;
}
private static double[][] QuickSort(double[][] input,int low,int high){
if(low>=high) return null ;
int first=low ;
int last=high ;
double[] key=input[low] ;
while(first<last){
while((first<last)&&(input[last][0]>=key[0])) --last ;
input[first]=input[last] ;
while((first<last)&&(input[first][0]<=key[0])) ++first ;
input[last]=input[first] ;
}
input[first]=key ;
double[][] res1,res2 ;
if (first-1>low) {res1=QuickSort(input,low,first-1) ;}
else if(first-1==low) {double[][] temp={input[low]} ;res1=temp ;}
else{res1=null ;}
if(high>first+1){res2=QuickSort(input,first+1,high) ;}
else if(high==first+1){double[][] temp={input[high]} ;res2=temp ;}
else{res2=null ;}
double[][] finalres ;
finalres=Combine(res1,res2,key) ;
return finalres ;
}
private static double[][] Combine(double[][] res1,double[][] res2,double[] key){
int len1,len2 ;
if(res1==null) len1=0 ;
else len1=res1.length ;
if(res2==null) len2=0 ;
else len2=res2.length ;
double[][] res=new double[len1+len2+1][3] ;
int index=0 ;
for(int i=0;i<len1;i++) res[index++]=res1[i] ;
res[index++]=key ;
for(int i=0;i<len2;i++) res[index++]=res2[i] ;
return res ;
}
//-------除錯用函式----------------------
private static void print(double[][] input){ //// used for debug
if(input!=null){
int len1=input.length ;
int len2=input[0].length ;
for(int i=0;i<len1;i++){
for(int j=0;j<len2;j++){
System.out.print(input[i][j]+"\t");
}
System.out.print('\n');
}
}else System.out.println("ERROR:輸入二維陣列為空") ;
}
}
Hunt類有3個值,type指的是計算得到的最優的分類屬性,valve_value指的是相應的最優分類值,min_entropy指的是分類以後的熵。
為了構造的函式,主要就是先用preDeal函式將假設的屬性值與類繫結到一個二維陣列中(這麼做是為了增加通用性)然後使用FindBestValue來尋找該屬性中最優值。即首先將這些元素排序,然後依次檢驗元素之間的差值對應的熵,從中選出最小的熵作為BestValue。這樣,就能得到這個屬性中最優差值對應的最小的熵。把4個屬性對應的4個最小熵對比,就能得到熵最小的那個類,作為最優分類屬性
5.Estimate
import java.util.*;
public class Estimate {
ArrayList<IrisData> list0 ;
ArrayList<IrisData> list1 ;
IrisNode examtree ;
double ErrorRatio ;
public Estimate(IrisNode rule,IrisData[] examset){
this.list0=new ArrayList() ;
this.list1=new ArrayList() ;
this.examtree=examTree(rule,examset) ;
this.ErrorRatio=getErrorRatio(this.examtree) ;
}
private double getErrorRatio(IrisNode node){
if (node.datalist.length==0) return 0 ;
if(node.nodeType==-1){
double len1=0,len2=0 ;
double ratio1=1,ratio2=1 ;
if(node.leftChild==null) len1=0 ;
else {
len1=node.leftChild.datalist.length ;
ratio1=getErrorRatio(node.leftChild) ;
}
if(node.rightChild==null) len2=0 ;
else {
len2=node.rightChild.datalist.length ;
ratio2=getErrorRatio(node.rightChild) ;
}
double noderatio=(len1*ratio1+len2*ratio2)/(len1+len2) ;
return noderatio ;
}else{
if(node.nodeType==0){
double len=node.datalist.length ;
double num=0 ;
for(int i=0;i<len;i++){
this.list0.add(node.datalist[i]) ;
if(node.datalist[i].tempType==1) num++ ;
}
double noderatio=num/len ;
return noderatio ;
}
if(node.nodeType==1){
double len=node.datalist.length ;
double num=0 ;
for(int i=0;i<len;i++){
this.list1.add(node.datalist[i]) ;
if(node.datalist[i].tempType==0) num++ ;
}
double noderatio=num/len ;
return noderatio ;
}
return -1 ;
}
}
private IrisNode examTree(IrisNode node,IrisData[] data){
node.datalist=data ;
node.formerEntropy=getIrisDataListEntropy(data) ;
if (node.nodeType==-1) { //this node is not a leaf node
IrisData[] left=IrisNode.Divide(data, node.divideType, node.valveValue, 0) ;
IrisData[] right=IrisNode.Divide(data, node.divideType, node.valveValue, 1) ;
if (left.length==0) node.leftChild=null ;
else node.leftChild=examTree(node.leftChild,left) ;
if(right.length==0) node.rightChild=null ;
else node.rightChild=examTree(node.rightChild,right) ;
return node ;
}else{ // this node is a leaf node
node.leftChild=null ;
node.rightChild=null ;
return node ;
}
}
public double getFinalEntropy(IrisNode input){
double rs=-1 ;
if ((input.leftChild==null)||(input.rightChild==null)){
rs=getIrisDataListEntropy(input.datalist) ;
return rs ;
}else{
double rs_1=getFinalEntropy(input.leftChild) ;
double len1=input.leftChild.datalist.length ;
double rs_2=getFinalEntropy(input.rightChild) ;
double len2=input.rightChild.datalist.length ;
rs=(rs_1*len1+rs_2*len2)/(len1+len2) ;
return rs ;
}
}
//Private Methods
private static double getIrisDataListEntropy(IrisData[] input){
DataProperty dp=new DataProperty() ;
double rs_entropy=-1 ;
//通過tempType的值來計算irisdata陣列的熵
//tempType只有3個值,0表示類1,1表示類2,-1表示其他類 一般用於表示異常
int num1=0,num2=0 ;
for(int i=0;i<input.length;i++){
if(input[i].tempType==0) num1++ ;
if(input[i].tempType==1) num2++ ;
}
rs_entropy=dp.getEntropy(num1, num2) ;
return rs_entropy ;
}
}
這個類主要用於評估生成的決策樹的效能,目前不是很完善,只能計算檢驗集使用該決策樹的錯誤率。
examTree將檢驗集應用於之前生成的決策樹,重新生成節點的左右子樹,對於空的子樹,進行封閉處理。
getErrorRatio利用遞迴的方法計算錯誤率。
6.ExcelPrint
import java.io.File;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
public class ExcelPrint {
public ExcelPrint(){
}
public void PrintIrisDataArray(IrisData[] input,String filename){
try{
String rootname="C:\\Users\\multiangle\\Desktop\\" ;
String path=rootname+filename+".xls" ;
File file=new File(path) ;
WritableSheet sheet ;
WritableWorkbook book ;
if (file.exists()) {
Workbook wb=Workbook.getWorkbook(file) ;
book=Workbook.createWorkbook(file, wb) ;
int sheetnum=book.getNumberOfSheets() ;
sheet=book.createSheet("第"+sheetnum+"頁", sheetnum) ;
System.out.println("正在第"+sheetnum+"頁列印IrisData陣列");
}else {
book=Workbook.createWorkbook(new File(path)) ;
sheet=book.createSheet("第0頁", 0) ;
System.out.println("正在第0頁列印IrisData陣列");
}
//System.out.println("已獲取到需要的表單");
String[] name={"SetNum","Sepal Length","Sepan Width","Petal Length","Petal Width","Type","tempType"} ;
for(int i=0;i<7;i++){
Label temp=new Label(i,0,name[i]) ;
sheet.addCell(temp);
}
int len=input.length ;
int row=1 ;
for(int i=0;i<len;i++){
int col=0 ;
Label cell1=new Label(col++,row,String.valueOf(input[i].SetNum)) ;
Label cell2=new Label(col++,row,String.valueOf(input[i].SL)) ;
Label cell3=new Label(col++,row,String.valueOf(input[i].SW)) ;
Label cell4=new Label(col++,row,String.valueOf(input[i].PL)) ;
Label cell5=new Label(col++,row,String.valueOf(input[i].PW)) ;
Label cell6=new Label(col++,row,String.valueOf(input[i].Type)) ;
Label cell7=new Label(col++,row,String.valueOf(input[i].tempType)) ;
sheet.addCell(cell1);
sheet.addCell(cell2);
sheet.addCell(cell3);
sheet.addCell(cell4);
sheet.addCell(cell5);
sheet.addCell(cell6);
sheet.addCell(cell7);
row++ ;
}
book.write() ;
book.close();
}catch(Exception e){
System.out.println(e) ;
System.out.println("ERROR:ExcelPrint") ;
}
}
public void PrintIrisDataArray(IrisData[] input,String filename,String description){
try{
String rootname="C:\\Users\\multiangle\\Desktop\\" ;
String path=rootname+filename+".xls" ;
File file=new File(path) ;
WritableSheet sheet ;
WritableWorkbook book ;
if (file.exists()) {
Workbook wb=Workbook.getWorkbook(file) ;
book=Workbook.createWorkbook(file, wb) ;
int sheetnum=book.getNumberOfSheets() ;
sheet=book.createSheet("第"+sheetnum+"頁", sheetnum) ;
System.out.println("正在第"+sheetnum+"頁列印IrisData陣列");
}else {
book=Workbook.createWorkbook(new File(path)) ;
sheet=book.createSheet("第0頁", 0) ;
System.out.println("正在第0頁列印IrisData陣列");
}
//System.out.println("已獲取到需要的表單");
Label descrip=new Label(0,0,description) ;
sheet.addCell(descrip) ;
String[] name={"SetNum","Sepal Length","Sepan Width","Petal Length","Petal Width","Type","tempType"} ;
for(int i=0;i<7;i++){
Label temp=new Label(i,1,name[i]) ;
sheet.addCell(temp);
}
int len=input.length ;
int row=2 ;
for(int i=0;i<len;i++){
int col=0 ;
Label cell1=new Label(col++,row,String.valueOf(input[i].SetNum)) ;
Label cell2=new Label(col++,row,String.valueOf(input[i].SL)) ;
Label cell3=new Label(col++,row,String.valueOf(input[i].SW)) ;
Label cell4=new Label(col++,row,String.valueOf(input[i].PL)) ;
Label cell5=new Label(col++,row,String.valueOf(input[i].PW)) ;
Label cell6=new Label(col++,row,String.valueOf(input[i].Type)) ;
Label cell7=new Label(col++,row,String.valueOf(input[i].tempType)) ;
sheet.addCell(cell1);
sheet.addCell(cell2);
sheet.addCell(cell3);
sheet.addCell(cell4);
sheet.addCell(cell5);
sheet.addCell(cell6);
sheet.addCell(cell7);
row++ ;
}
book.write() ;
book.close();
}catch(Exception e){
System.out.println(e) ;
System.out.println("ERROR:ExcelPrint") ;
}
}
public void PrintIrisData(IrisData[] input,String filename,int sheetnum){ //要注意 input sheet num>current sheet num+1的情況可能出現的BUG
//待定
}
private static boolean CreateExcel(String filename){
try{
WritableWorkbook book=Workbook.createWorkbook(new File(filename)); //開啟檔案
WritableSheet sheet=book.createSheet("FirstPage",0) ; //生成名為“FirstPage”的工作表,引數0表示這是第一頁
Label label=new Label(0,0,"") ;
sheet.addCell(label);
book.write();
book.close();
return true;
}catch(Exception e){
System.out.println("ERROR:CreateExcel") ;
return false ;
}
}
private static boolean CreateExcel(String filename,String sheetname){
try{
WritableWorkbook book=Workbook.createWorkbook(new File(filename)); //開啟檔案