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 |