Morpheus 庫旨在促進涉及大型資料集的高效能分析軟體的開發,以便在 Java 虛擬機器 (JVM) 上進行離線和即時分析。該函式庫是用 Java 8 編寫的,廣泛使用了 lambda,但所有 JVM 語言都可以存取。
有關範例的詳細文檔,請參閱此處
Morpheus 的核心提供了一種通用的二維記憶體高效表格資料結構,稱為DataFrame
,類似於R 中首先流行的那種。它們不適合適合大規模生產系統,因為它們變得極難維護,重構起來很危險。 Morpheus 程式庫試圖保留DataFrame
概念的強大功能和多功能性,同時提供更類型安全性和自描述的介面集,這將使開發、維護和擴展程式碼複雜性變得更加容易。
Morpheus 函式庫的另一個優點是,鑑於 Java 虛擬機強大的執行緒功能,它非常擅長在多核心處理器架構上進行擴充。 Morpheus DataFrame
上的許多操作可以透過簡單地在您想要操作的實體上呼叫parallel()
來無縫地並行運行,就像 Java 8 Streams 一樣。在內部,這些並行實現基於 Fork & Join 框架,隨著 CPU 核心的添加,某些類型的操作的效能得到了近乎線性的改進。
Morpheus DataFrame
是一種列式儲存結構,其中每一列都由 Morpheus Array
表示,該陣列有多種實作方式,包括密集、稀疏和記憶體映射版本。 Morpheus 陣列經過最佳化,並且盡可能由原始本機 Java 陣列支援(甚至對於LocalDate
、 LocalDateTime
等類型),因為從儲存、存取和垃圾收集的角度來看,它們的效率要高得多。記憶體映射的 Morpheus Arrays
雖然仍處於實驗階段,但允許使用由檔案支援的堆外儲存來建立非常大的DataFrames
。
雖然 Morpheus DataFrame
的完整功能集仍在不斷發展,但已經有許多強大的 API 可以輕鬆影響複雜的轉換和分析操作。有一些標準函數可以計算總結統計量、執行各種類型的線性迴歸、應用主成分分析 (PCA),僅舉幾例。 DataFrame
在行和列維度上都有索引,讓資料沿著任一軸高效排序、切片、分組和聚合。
Morpheus 還旨在提供一種標準機制來載入來自各種資料提供者的資料集。希望社群能夠接受該 API,以擴大支援的資料來源目錄。目前,提供者可以從 Quandl、聯準會、世界銀行、雅虎財經和Google財經載入資料。
考慮可在此處存取的機動車輛特徵資料集。下面的程式碼將此 CSV 資料載入到 Morpheus DataFrame
中,過濾行以僅包含功率重量比 > 0.1(其中重量轉換為公斤)的車輛,然後新增一列來記錄高速公路和高速公路之間的相對效率城市里程(MPG),按此新新增的欄位以降序對資料列進行排序,最後將轉換後的結果記錄到CSV 檔案中。
DataFrame . read (). csv ( options -> {
options . setResource ( "http://zavtech.com/data/samples/cars93.csv" );
options . setExcludeColumnIndexes ( 0 );
}). rows (). select ( row -> {
double weightKG = row . getDouble ( "Weight" ) * 0.453592d ;
double horsepower = row . getDouble ( "Horsepower" );
return horsepower / weightKG > 0.1d ;
}). cols (). add ( "MPG(Highway/City)" , Double . class , v -> {
double cityMpg = v . row (). getDouble ( "MPG.city" );
double highwayMpg = v . row (). getDouble ( "MPG.highway" );
return highwayMpg / cityMpg ;
}). rows (). sort ( false , "MPG(Highway/City)" ). write (). csv ( options -> {
options . setFile ( "/Users/witdxav/cars93m.csv" );
options . setTitle ( "DataFrame" );
});
此範例示範了 Morpheus API 的功能性質,其中許多方法傳回類型實際上是DataFrame
,因此允許這種形式的方法連結。在此範例中,方法csv()
、 select()
、 add()
和sort()
皆傳回一個框架。在某些情況下,此方法所操作的幀是同一幀,或者在其他情況下,是所操作的幀的過濾器或淺表副本。本範例中轉換後的資料集的前 10 行如下所示,新新增的列出現在框架的最右側。
索引 |製造商 |型號|類型 |最低價格 |價格|最高價格 | MPG.city | MPG. 公路 |安全氣囊 |傳動系統 |氣缸 |引擎尺寸 |馬力 |轉速|每英里轉速 |人.trans.avail |油箱容量 |乘客 |長度 |軸距|寬度|轉圈|後座空間 |行李室 |重量 |產地 |製作| MPG(高速公路/城市)| -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- 9 |凱迪拉克|德維爾 |大| 33.0000 | 34.7000 | 36.3000 | 16 | 16 25 | 25僅司機 |前| 8 | 4.9000 | 200 | 200 4100 | 4100 1510 | 1510沒有 | 18.0000 | 6 | 206 | 206 114 | 114 73 | 73 43 | 43 35 | 35 18 | 18 3620 | 3620美國 |凱迪拉克帝維爾 | 1.5625 | 1.5625 10 | 10凱迪拉克|塞維利亞 |中型| 37.5000 | 40.1000 | 42.7000 | 16 | 16 25 | 25司機和乘客|前| 8 | 4.6000 | 295 | 295 6000 | 1985 |沒有 | 20.0000 | 5 | 204 | 204 111 | 111 74 | 74 44 | 44 31 | 14 | 14 3935 | 3935美國 |凱迪拉克塞維利亞 | 1.5625 | 1.5625 70 | 70奧茲莫比爾 |八十八 |大| 19.5000 | 20.7000 | 20.7000 21.9000 | 19 | 19 28 | 28僅司機 |前| 6 | 3.8000 | 170 | 170 4800 | 1570 | 1570沒有 | 18.0000 | 6 | 201 | 201 111 | 111 74 | 74 42 | 42 31.5 | 31.5 17 | 17 3470 | 3470美國 |奧茲莫比爾八十八 | 1.47368421 | 74 | 74龐蒂亞克|火鳥 |運動型 | 14.0000 | 17.7000 | 21.4000 | 19 | 19 28 | 28司機和乘客|後部| 6 | 3.4000 | 160 | 160 4600 | 4600 1805 | 1805是的 | 15.5000 | 15.5000 4 | 196 | 196 101 | 101 75 | 75 43 | 43 25 | 25 13 | 3240 | 3240美國 |龐蒂亞克火鳥 | 1.47368421 | 6 |別克|勒薩布雷 |大| 19.9000 | 20.8000 | 21.7000 | 19 | 19 28 | 28僅司機 |前| 6 | 3.8000 | 170 | 170 4800 | 1570 | 1570沒有 | 18.0000 | 6 | 200 | 200 111 | 111 74 | 74 42 | 42 30.5 | 30.5 17 | 17 3470 | 3470美國 |別克LeSabre | 1.47368421 | 13 |雪佛蘭 |科邁羅|運動型 | 13.4000 | 15.1000 | 16.8000 | 19 | 19 28 | 28司機和乘客|後部| 6 | 3.4000 | 160 | 160 4600 | 4600 1805 | 1805是的 | 15.5000 | 15.5000 4 | 193 | 193 101 | 101 74 | 74 43 | 43 25 | 25 13 | 3240 | 3240美國 |雪佛蘭科邁羅 | 1.47368421 | 76 | 76龐蒂亞克|博納維爾 |大| 19.4000 | 24.4000 | 29.4000 | 19 | 19 28 | 28司機和乘客|前| 6 | 3.8000 | 170 | 170 4800 | 1565 | 1565沒有 | 18.0000 | 6 | 177 | 177 111 | 111 74 | 74 43 | 43 30.5 | 30.5 18 | 18 3495 | 3495美國 |龐蒂亞克博納維爾| 1.47368421 | 56 | 56馬自達| RX-7 |運動型 | 32.5000 | 32.5000 | 32.5000 | 17 | 17 25 | 25僅司機 |後部|旋轉| 1.3000 | 1.3000 255 | 255 6500 | 2325 | 2325是的 | 20.0000 | 2 | 169 | 169 96 | 96 69 | 69 37 | 37不適用 |不適用 | 2895 | 2895非美國 |馬自達RX-7 | 1.47058824 | 18 | 18雪佛蘭 |克爾維特 |運動型 | 34.6000 | 38.0000 | 41.5000 | 17 | 17 25 | 25僅司機 |後部| 8 | 5.7000 | 300 | 300 5000 | 1450 | 1450是的 | 20.0000 | 2 | 179 | 179 96 | 96 74 | 74 43 | 43不適用 |不適用 | 3380 | 3380美國 |雪佛蘭克爾維特 | 1.47058824 | 51 | 51林肯 |鎮_車 |大| 34.4000 | 36.1000 | 37.8000 | 18 | 18 26 | 26司機和乘客|後部| 8 | 4.6000 | 210 | 210 4600 | 4600 1840 | 1840沒有 | 20.0000 | 6 | 219 | 219 117 | 117 77 | 77 45 | 45 31.5 | 31.5 22 | 22 4055 | 4055美國 |林肯鎮_汽車 | 1.44444444 |
Morpheus API 包含一個迴歸接口,以便使用 OLS、WLS 或 GLS 將資料擬合到線性模型。下面的程式碼使用上一個範例中引入的相同汽車資料集,並在EngineSize上回歸馬力。此程式碼範例將模型結果列印到標準輸出(如下所示),然後建立一個清晰顯示迴歸線的散佈圖。
//Load the data
DataFrame < Integer , String > data = DataFrame . read (). csv ( options -> {
options . setResource ( "http://zavtech.com/data/samples/cars93.csv" );
options . setExcludeColumnIndexes ( 0 );
});
//Run OLS regression and plot
String regressand = "Horsepower" ;
String regressor = "EngineSize" ;
data . regress (). ols ( regressand , regressor , true , model -> {
System . out . println ( model );
DataFrame < Integer , String > xy = data . cols (). select ( regressand , regressor );
Chart . create (). withScatterPlot ( xy , false , regressor , chart -> {
chart . title (). withText ( regressand + " regressed on " + regressor );
chart . subtitle (). withText ( "Single Variable Linear Regression" );
chart . plot (). style ( regressand ). withColor ( Color . RED ). withPointsVisible ( true );
chart . plot (). trend ( regressand ). withColor ( Color . BLACK );
chart . plot (). axes (). domain (). label (). withText ( regressor );
chart . plot (). axes (). domain (). format (). withPattern ( "0.00;-0.00" );
chart . plot (). axes (). range ( 0 ). label (). withText ( regressand );
chart . plot (). axes (). range ( 0 ). format (). withPattern ( "0;-0" );
chart . show ();
});
return Optional . empty ();
});
==================================================== = ============================================= 線性迴歸結果 ==================================================== = ============================================= 型號:OLS R 平方:0.5360 觀察值:93 R 平方(調整後):0.5309 DF 模型:1 F 統計量:105.1204 DF 殘差:91 F 統計量(機率):1.11E-16 標準錯誤:35.8717 運行時間(毫秒)52 杜賓-沃森:1.9591 ==================================================== = ============================================= 索引 |參數| STD_錯誤| T_STAT | P_值 | CI_LOWER | CI_上部 | -------------------------------------------------- -------------------------------------------------- ------ 攔截| 45.2195 | 45.2195 10.3119 | 4.3852 | 3.107E-5 | 3.107E-5 24.736 | 24.736 65.7029 | 65.7029 引擎尺寸 | 36.9633 | 36.9633 3.6052 | 3.6052 10.2528 | 7.573E-17 | 7.573E-17 29.802 | 29.802 44.1245 | 44.1245 ==================================================== = =============================================
透過英國政府開放資料計劃,可以存取從 1995 年至今的所有英國住宅房地產交易記錄。資料以CSV格式呈現,包含眾多列,包括交易日期、付款價格、完全合格的地址(包括郵遞區號)、房產類型、租賃類型等資訊。
首先,我們編寫一個函數來從 Amazon S3 儲存桶載入這些 CSV 文件,由於它們每年儲存一個文件,因此我們相應地提供了一個參數化函數。鑑於我們的分析需求,不需要載入文件中的所有列,因此下面我們只選擇讀取索引為1、2、4和11處的列。有意義的名稱,以使後續訪問更加清晰。
/**
* Loads UK house price from the Land Registry stored in an Amazon S3 bucket
* Note the data does not have a header, so columns will be named Column-0, Column-1 etc...
* @param year the year for which to load prices
* @return the resulting DataFrame, with some columns renamed
*/
private DataFrame < Integer , String > loadHousePrices ( Year year ) {
String resource = "http://prod.publicdata.landregistry.gov.uk.s3-website-eu-west-1.amazonaws.com/pp-%s.csv" ;
return DataFrame . read (). csv ( options -> {
options . setResource ( String . format ( resource , year . getValue ()));
options . setHeader ( false );
options . setCharset ( StandardCharsets . UTF_8 );
options . setIncludeColumnIndexes ( 1 , 2 , 4 , 11 );
options . getFormats (). setParser ( "TransactDate" , Parser . ofLocalDate ( "yyyy-MM-dd HH:mm" ));
options . setColumnNameMapping (( colName , colOrdinal ) -> {
switch ( colOrdinal ) {
case 0 : return "PricePaid" ;
case 1 : return "TransactDate" ;
case 2 : return "PropertyType" ;
case 3 : return "City" ;
default : return colName ;
}
});
});
}
以下我們使用這些數據來計算 1995 年至 2014 年間英國部分最大城市每年的公寓名目價格中位數(未經過通貨膨脹調整)。 1993 年至2014 年間,未經過濾的資料集中大約有2000 萬筆記錄,雖然載入和解析需要相當長的時間(大約3.5GB 資料),但Morpheus 在大約5 秒內執行了程式碼的分析部分(不包括載入時間)在 2013 年末購買的標準 Apple Macbook Pro results.rows().keys().parallel()
。
//Create a data frame to capture the median prices of Apartments in the UK'a largest cities
DataFrame < Year , String > results = DataFrame . ofDoubles (
Range . of ( 1995 , 2015 ). map ( Year :: of ),
Array . of ( "LONDON" , "BIRMINGHAM" , "SHEFFIELD" , "LEEDS" , "LIVERPOOL" , "MANCHESTER" )
);
//Process yearly data in parallel to leverage all CPU cores
results . rows (). keys (). parallel (). forEach ( year -> {
System . out . printf ( "Loading UK house prices for %s... n " , year );
DataFrame < Integer , String > prices = loadHousePrices ( year );
prices . rows (). select ( row -> {
//Filter rows to include only apartments in the relevant cities
final String propType = row . getValue ( "PropertyType" );
final String city = row . getValue ( "City" );
final String cityUpperCase = city != null ? city . toUpperCase () : null ;
return propType != null && propType . equals ( "F" ) && results . cols (). contains ( cityUpperCase );
}). rows (). groupBy ( "City" ). forEach ( 0 , ( groupKey , group ) -> {
//Group row filtered frame so we can compute median prices in selected cities
final String city = groupKey . item ( 0 );
final double priceStat = group . colAt ( "PricePaid" ). stats (). median ();
results . data (). setDouble ( year , city , priceStat );
});
});
//Map row keys to LocalDates, and map values to be percentage changes from start date
final DataFrame < LocalDate , String > plotFrame = results . mapToDoubles ( v -> {
final double firstValue = v . col (). getDouble ( 0 );
final double currentValue = v . getDouble ();
return ( currentValue / firstValue - 1d ) * 100d ;
}). rows (). mapKeys ( row -> {
final Year year = row . key ();
return LocalDate . of ( year . getValue (), 12 , 31 );
});
//Create a plot, and display it
Chart . create (). withLinePlot ( plotFrame , chart -> {
chart . title (). withText ( "Median Nominal House Price Changes" );
chart . title (). withFont ( new Font ( "Arial" , Font . BOLD , 14 ));
chart . subtitle (). withText ( "Date Range: 1995 - 2014" );
chart . plot (). axes (). domain (). label (). withText ( "Year" );
chart . plot (). axes (). range ( 0 ). label (). withText ( "Percent Change from 1995" );
chart . plot (). axes (). range ( 0 ). format (). withPattern ( "0.##'%';-0.##'%'" );
chart . plot (). style ( "LONDON" ). withColor ( Color . BLACK );
chart . legend (). on (). bottom ();
chart . show ();
});
下圖顯示了所選城市子集中公寓名義中位數價格的百分比變化。它表明,倫敦名義房價並未因全球金融危機(GFC)而出現任何下降,但並非英國所有城市都具有彈性。稍微令人驚訝的是,與倫敦相比,一些不太富裕的北方城市在2003年至2006年期間的升值率更高。需要注意的一件事是,雖然倫敦名目價格沒有任何下降,但歐元和美元肯定出現了相當嚴重的調整,因為英鎊在全球金融危機期間兌這些貨幣大幅貶值。
透過簡單的圖表抽象 API以及支援 JFreeChart 和 Google Charts(以及其他可根據大眾需求遵循的其他圖表)的適配器,可以輕鬆地在 Morpheus DataFrames
中可視化資料。這種設計使得可以透過相同的程式介面產生互動式 Java Swing 圖表以及基於 HTML5 瀏覽器的圖表。有關如何使用此 API 的更多詳細信息,請參閱此處有關可視化的部分和此處的程式碼。
Morpheus 已發佈到 Maven Central,因此可以輕鬆地將其新增為您選擇的建置工具中的依賴項。程式碼庫目前分為 5 個儲存庫,以允許每個模組獨立發展。核心模組被恰當地命名為 morpheus-core,它是所有其他模組所依賴的基礎庫。各種 Maven 工件如下:
睡眠核心
包含 Morpheus Arrays、DataFrames 和其他關鍵介面和實作的基礎庫。
< dependency >
< groupId >com.zavtech</ groupId >
< artifactId >morpheus-core</ artifactId >
< version >${VERSION}</ version >
</ dependency >
睡眠可視化
用於在圖表和表格中顯示DataFrames
可視化組件。
< dependency >
< groupId >com.zavtech</ groupId >
< artifactId >morpheus-viz</ artifactId >
< version >${VERSION}</ version >
</ dependency >
睡眠庫德爾
從 Quandl 載入資料的適配器
< dependency >
< groupId >com.zavtech</ groupId >
< artifactId >morpheus-quandl</ artifactId >
< version >${VERSION}</ version >
</ dependency >
睡眠谷歌
從 Google Finance 載入資料的適配器
< dependency >
< groupId >com.zavtech</ groupId >
< artifactId >morpheus-google</ artifactId >
< version >${VERSION}</ version >
</ dependency >
雅虎睡眠
從雅虎財經加載資料的適配器
< dependency >
< groupId >com.zavtech</ groupId >
< artifactId >morpheus-yahoo</ artifactId >
< version >${VERSION}</ version >
</ dependency >
已使用 Google 網上論壇設置了問答論壇,可在此處訪問
可以在此處線上存取 Morpheus Javadocs。
可以在此處存取持續整合建置伺服器,該伺服器在每次合併後建置程式碼。
Morpheus 是根據 Apache Software Foundation License Version 2 發布的。