| 1 | #Region "Microsoft.VisualBasic::85535aa28678e76ae6415cfda4084efb, Microsoft.VisualBasic.Core\Extensions\Collection\Matrix.vb" |
| 2 | |
| 3 | ' Author: |
| 4 | ' |
| 5 | ' asuka (amethyst.asuka@gcmodeller.org) |
| 6 | ' xie (genetics@smrucc.org) |
| 7 | ' xieguigang (xie.guigang@live.com) |
| 8 | ' |
| 9 | ' Copyright (c) 2018 GPL3 Licensed |
| 10 | ' |
| 11 | ' |
| 12 | ' GNU GENERAL PUBLIC LICENSE (GPL3) |
| 13 | ' |
| 14 | ' |
| 15 | ' This program is free software: you can redistribute it and/or modify |
| 16 | ' it under the terms of the GNU General Public License as published by |
| 17 | ' the Free Software Foundation, either version 3 of the License, or |
| 18 | ' (at your option) any later version. |
| 19 | ' |
| 20 | ' This program is distributed in the hope that it will be useful, |
| 21 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 22 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 23 | ' GNU General Public License for more details. |
| 24 | ' |
| 25 | ' You should have received a copy of the GNU General Public License |
| 26 | ' along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 27 | |
| 28 | |
| 29 | |
| 30 | ' /********************************************************************************/ |
| 31 | |
| 32 | ' Summaries: |
| 33 | |
| 34 | ' Module MatrixExtensions |
| 35 | ' |
| 36 | ' Function: DATA, GetCol, GetRow, GetSize, MAT |
| 37 | ' (+2 Overloads) Matrix, RowIterator, SetCol, SetRow, ToFloatMatrix |
| 38 | ' ToMatrix, ToVectorList |
| 39 | ' |
| 40 | ' /********************************************************************************/ |
| 41 | |
| 42 | #End Region |
| 43 | |
| 44 | Imports System.Drawing |
| 45 | Imports System.Runtime.CompilerServices |
| 46 | Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel |
| 47 | Imports Microsoft.VisualBasic.Language |
| 48 | Imports Microsoft.VisualBasic.Linq |
| 49 | |
| 50 | Public Module MatrixExtensions |
| 51 | |
| 52 | ''' <summary> |
| 53 | ''' 将数据集之中的虽有属性值取出来构建一个矩阵 |
| 54 | ''' </summary> |
| 55 | ''' <param name="data"></param> |
| 56 | ''' <returns></returns> |
| 57 | Public Iterator Function Matrix(Of T, DataSet As DynamicPropertyBase(Of T))(data As IEnumerable(Of DataSet)) As IEnumerable(Of T()) |
| 58 | With data.ToArray |
| 59 | Dim allFields = .Select(Function(x) x.Properties.Keys) _ |
| 60 | .IteratesALL _ |
| 61 | .Distinct _ |
| 62 | .ToArray |
| 63 | |
| 64 | For Each x As DataSet In .ByRef |
| 65 | ' 利用属性名列表做subset,得到每一个数据对象的属性向量 |
| 66 | Yield x.ItemValue(allFields) |
| 67 | Next |
| 68 | End With |
| 69 | End Function |
| 70 | |
| 71 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
| 72 | <Extension> |
| 73 | Public Function Matrix(Of DataSet As DynamicPropertyBase(Of Double))(data As IEnumerable(Of DataSet)) As IEnumerable(Of Double()) |
| 74 | Return Matrix(Of Double, DataSet)(data) |
| 75 | End Function |
| 76 | |
| 77 | '<MethodImpl(MethodImplOptions.AggressiveInlining)> |
| 78 | '<Extension> |
| 79 | 'Public Function Matrix(Of DataSet As DynamicPropertyBase(Of String))(data As IEnumerable(Of DataSet)) As IEnumerable(Of String()) |
| 80 | ' Return Matrix(Of String, DataSet)(data) |
| 81 | 'End Function |
| 82 | |
| 83 | ''' <summary> |
| 84 | ''' Converts a <see cref="DataTable"/> to a 2-dimensional array |
| 85 | ''' </summary> |
| 86 | ''' <param name="table">A System.Data.DataTable containing data to cluster</param> |
| 87 | ''' <returns>A 2-dimensional array containing data to cluster</returns> |
| 88 | <Extension> Public Function ToFloatMatrix(table As DataTable) As Double(,) |
| 89 | Dim rowCount As Integer = table.Rows.Count |
| 90 | Dim fieldCount As Integer = table.Columns.Count |
| 91 | Dim dataPoints As Double(,) |
| 92 | Dim fieldValue As Double = 0.0 |
| 93 | Dim row As DataRow |
| 94 | |
| 95 | dataPoints = New Double(rowCount - 1, fieldCount - 1) {} |
| 96 | |
| 97 | For rowPosition As Integer = 0 To rowCount - 1 |
| 98 | row = table.Rows(rowPosition) |
| 99 | |
| 100 | For fieldPosition As Integer = 0 To fieldCount - 1 |
| 101 | Try |
| 102 | fieldValue = Double.Parse(row(fieldPosition).ToString()) |
| 103 | Catch ex As Exception |
| 104 | Dim msg$ = $"Invalid row at {rowPosition.ToString()} and field {fieldPosition.ToString()}" |
| 105 | ex = New InvalidCastException(msg, ex) |
| 106 | ex.PrintException |
| 107 | |
| 108 | Throw ex |
| 109 | End Try |
| 110 | |
| 111 | dataPoints(rowPosition, fieldPosition) = fieldValue |
| 112 | Next |
| 113 | Next |
| 114 | |
| 115 | Return dataPoints |
| 116 | End Function |
| 117 | |
| 118 | ''' <summary> |
| 119 | ''' Gets property field data from a generic data frame |
| 120 | ''' </summary> |
| 121 | ''' <typeparam name="T"></typeparam> |
| 122 | ''' <param name="dataframe"></param> |
| 123 | ''' <param name="property$"></param> |
| 124 | ''' <returns></returns> |
| 125 | ''' |
| 126 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
| 127 | <Extension> |
| 128 | Public Function DATA(Of T)(dataframe As IEnumerable(Of DynamicPropertyBase(Of T)), property$) As T() |
| 129 | Return dataframe.Select(Function(d) d([property])).ToArray |
| 130 | End Function |
| 131 | |
| 132 | ''' <summary> |
| 133 | ''' Create an empty matrix with m row and n cols. |
| 134 | ''' (生成一个有m行n列的矩阵,但是是使用数组来表示的) |
| 135 | ''' </summary> |
| 136 | ''' <typeparam name="T"></typeparam> |
| 137 | ''' <param name="m">m Rows</param> |
| 138 | ''' <param name="n">n Cols</param> |
| 139 | ''' <returns></returns> |
| 140 | Public Function MAT(Of T)(m%, n%) As T()() |
| 141 | Dim newMAT As T()() = New T(m - 1)() {} |
| 142 | |
| 143 | For i As Integer = 0 To m - 1 |
| 144 | newMAT(i) = New T(n - 1) {} |
| 145 | Next |
| 146 | |
| 147 | Return newMAT |
| 148 | End Function |
| 149 | |
| 150 | ''' <summary> |
| 151 | ''' Convert the data collection into a matrix value. |
| 152 | ''' </summary> |
| 153 | ''' <typeparam name="T"></typeparam> |
| 154 | ''' <param name="source">The elements number in each collection should be agreed!(要求集合之中的每一列之中的数据的元素数目都相等)</param> |
| 155 | ''' <returns></returns> |
| 156 | ''' <remarks></remarks> |
| 157 | <Extension> Public Function ToMatrix(Of T)(source As IEnumerable(Of IEnumerable(Of T))) As T(,) |
| 158 | Dim array As IEnumerable(Of T)() = source.ToArray |
| 159 | Dim width As Integer = array(Scan0).Count |
| 160 | Dim height As Integer = array.Length |
| 161 | Dim M As T(,) = New T(height - 1, width - 1) {} |
| 162 | |
| 163 | For i As Integer = 0 To height - 1 |
| 164 | Dim V As T() = array(i).ToArray |
| 165 | |
| 166 | For j As Integer = 0 To width - 1 |
| 167 | M(i, j) = V(j) |
| 168 | Next |
| 169 | Next |
| 170 | |
| 171 | Return M |
| 172 | End Function |
| 173 | |
| 174 | ''' <summary> |
| 175 | ''' Convert the matrix data into a collection of collection data type.(将矩阵对象转换为集合的集合的类型) |
| 176 | ''' </summary> |
| 177 | ''' <typeparam name="T"></typeparam> |
| 178 | ''' <param name="MAT"></param> |
| 179 | ''' <returns></returns> |
| 180 | ''' <remarks></remarks> |
| 181 | ''' |
| 182 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
| 183 | <Extension> Public Function ToVectorList(Of T)(MAT As T(,)) As List(Of T()) |
| 184 | Return MAT.RowIterator.AsList |
| 185 | End Function |
| 186 | |
| 187 | #Region "Matrix Accessor Helper" |
| 188 | |
| 189 | ''' <summary> |
| 190 | ''' Get matrix width and height values. |
| 191 | ''' </summary> |
| 192 | ''' <typeparam name="T"></typeparam> |
| 193 | ''' <param name="m"></param> |
| 194 | ''' <returns></returns> |
| 195 | <Extension> |
| 196 | Public Function GetSize(Of T)(m As T(,)) As Size |
| 197 | Dim w As Integer = m.GetLength(1) |
| 198 | Dim h As Integer = m.GetLength(0) |
| 199 | |
| 200 | Return New Size With { |
| 201 | .Width = w, |
| 202 | .Height = h |
| 203 | } |
| 204 | End Function |
| 205 | |
| 206 | ''' <summary> |
| 207 | ''' Iterates each row data in a matrix type array. |
| 208 | ''' </summary> |
| 209 | ''' <typeparam name="T"></typeparam> |
| 210 | ''' <param name="MAT"></param> |
| 211 | ''' <returns></returns> |
| 212 | <Extension> |
| 213 | Public Iterator Function RowIterator(Of T)(MAT As T(,)) As IEnumerable(Of T()) |
| 214 | Dim size As Size = MAT.GetSize |
| 215 | Dim temp As T() |
| 216 | |
| 217 | For i As Integer = 0 To size.Height - 1 |
| 218 | temp = New T(size.Width - 1) {} |
| 219 | |
| 220 | For j As Integer = 0 To size.Width - 1 |
| 221 | temp(j) = MAT(i, j) |
| 222 | Next |
| 223 | |
| 224 | Yield temp |
| 225 | Next |
| 226 | End Function |
| 227 | |
| 228 | <Extension> |
| 229 | Public Iterator Function GetRow(Of T)(m As T(,), i%) As IEnumerable(Of T) |
| 230 | Dim size As Size = m.GetSize |
| 231 | |
| 232 | For j As Integer = 0 To size.Width - 1 |
| 233 | Yield m(i, j) |
| 234 | Next |
| 235 | End Function |
| 236 | |
| 237 | <Extension> |
| 238 | Public Function SetRow(Of T)(m As T(,), i%, data As IEnumerable(Of T)) As T(,) |
| 239 | Dim size As Size = m.GetSize |
| 240 | Dim j% = Scan0 |
| 241 | |
| 242 | For Each x As T In data |
| 243 | m(i, j) = x |
| 244 | j += 1 |
| 245 | |
| 246 | If j = size.Width Then |
| 247 | Exit For |
| 248 | End If |
| 249 | Next |
| 250 | |
| 251 | Return m |
| 252 | End Function |
| 253 | |
| 254 | <Extension> |
| 255 | Public Iterator Function GetCol(Of T)(m As T(,), j%) As IEnumerable(Of T) |
| 256 | Dim size As Size = m.GetSize |
| 257 | |
| 258 | For i As Integer = 0 To size.Height - 1 |
| 259 | Yield m(i, j) |
| 260 | Next |
| 261 | End Function |
| 262 | |
| 263 | <Extension> |
| 264 | Public Function SetCol(Of T)(m As T(,), j%, data As IEnumerable(Of T)) As T(,) |
| 265 | Dim size As Size = m.GetSize |
| 266 | Dim i% = Scan0 |
| 267 | |
| 268 | For Each x As T In data |
| 269 | m(i, j) = x |
| 270 | i += 1 |
| 271 | |
| 272 | If i = size.Height Then |
| 273 | Exit For |
| 274 | End If |
| 275 | Next |
| 276 | |
| 277 | Return m |
| 278 | End Function |
| 279 | #End Region |
| 280 | End Module |