From 082acae169164ba2f677d9ee773e99eb4dcfd8af Mon Sep 17 00:00:00 2001 From: wangfeng Date: Tue, 31 Jan 2023 20:17:52 +0800 Subject: [PATCH 1/3] =?UTF-8?q?#I6C2X4=E5=AE=9E=E7=8E=B0string=E7=9A=84ser?= =?UTF-8?q?ies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- series_xstring.go | 1 + 1 file changed, 1 insertion(+) diff --git a/series_xstring.go b/series_xstring.go index dbb9843..e51c959 100644 --- a/series_xstring.go +++ b/series_xstring.go @@ -5,6 +5,7 @@ import ( "reflect" ) +// SeriesString 字符串类型序列 type SeriesString struct { SeriesFrame Data []string -- Gitee From e136958aa4456e0a48638847f9b10817f051febf Mon Sep 17 00:00:00 2001 From: wangfeng Date: Tue, 31 Jan 2023 21:36:03 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Mean=E7=9A=84=E4=B8=80?= =?UTF-8?q?=E8=88=AC=E7=94=A8=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- algorithms/aggregates.go | 77 ++++++++++++++++++++++++++++++++++++++++ algorithms/max.go | 39 ++++++++++++++++++++ algorithms/min.go | 39 ++++++++++++++++++++ series_number.go | 9 +++++ 4 files changed, 164 insertions(+) create mode 100644 algorithms/aggregates.go create mode 100644 algorithms/max.go create mode 100644 algorithms/min.go create mode 100644 series_number.go diff --git a/algorithms/aggregates.go b/algorithms/aggregates.go new file mode 100644 index 0000000..cad707a --- /dev/null +++ b/algorithms/aggregates.go @@ -0,0 +1,77 @@ +package algorithms + +type Number interface { + ~int64 | float64 +} + +func Sum_Go[T Number](x []T) T { + sum := T(0) + for i := 0; i < len(x); i++ { + sum += x[i] + } + return sum +} + +func CumSum_Go[T Number](x []T) { + sum := T(0) + for i := 0; i < len(x); i++ { + sum += x[i] + x[i] = sum + } +} + +func Prod_Go[T Number](x []T) T { + prod := T(1) + for i := 0; i < len(x); i++ { + prod *= x[i] + } + return prod +} + +func CumProd_Go[T Number](x []T) { + prod := T(1) + for i := 0; i < len(x); i++ { + prod *= x[i] + x[i] = prod + } +} + +func Mean_Go[T Number](x []T) T { + return Sum_Go(x) / T(len(x)) +} + +//func Median_Go[T Number](x []T) T { +// if len(x)%2 == 1 { +// x = slices.Clone(x) +// i := len(x) / 2 +// partial.TopK(x, i+1) +// return x[i] +// } +// return Quantile_Go(x, T(0.5)) +//} +// +//func Quantile_Go[T Number](x []T, q T) T { +// if len(x) == 1 { +// return x[0] +// } +// if q == T(0) { +// return Min_Go(x) +// } +// if q == T(1) { +// return Max_Go(x) +// } +// x = slices.Clone(x) +// f := T(len(x)-1) * q +// i := int(math.Floor(float64(f))) +// if q < 0.5 { +// partial.TopK(x, i+2) +// a := Max_Go(x[:i+1]) +// b := x[i+1] +// return a + (b-a)*(f-T(i)) +// } else { +// partial.TopK(x, i+1) +// a := x[i] +// b := Min_Go(x[i+1:]) +// return a + (b-a)*(f-T(i)) +// } +//} diff --git a/algorithms/max.go b/algorithms/max.go new file mode 100644 index 0000000..478199f --- /dev/null +++ b/algorithms/max.go @@ -0,0 +1,39 @@ +package algorithms + +func Max_Go[T Number](x []T) T { + max := x[0] + for _, v := range x[1:] { + if v > max { + max = v + } + } + return max +} + +func ArgMax_Go[T Number](x []T) int { + max := x[0] + idx := 0 + for i, v := range x[1:] { + if v > max { + max = v + idx = 1 + i + } + } + return idx +} + +func Maximum_Go[T Number](x, y []T) { + for i := 0; i < len(x); i++ { + if y[i] > x[i] { + x[i] = y[i] + } + } +} + +func MaximumNumber_Go[T Number](x []T, a T) { + for i := 0; i < len(x); i++ { + if a > x[i] { + x[i] = a + } + } +} diff --git a/algorithms/min.go b/algorithms/min.go new file mode 100644 index 0000000..ca46745 --- /dev/null +++ b/algorithms/min.go @@ -0,0 +1,39 @@ +package algorithms + +func Min_Go[T Number](x []T) T { + min := x[0] + for _, v := range x[1:] { + if v < min { + min = v + } + } + return min +} + +func ArgMin_Go[T Number](x []T) int { + min := x[0] + idx := 0 + for i, v := range x[1:] { + if v < min { + min = v + idx = 1 + i + } + } + return idx +} + +func Minimum_Go[T Number](x, y []T) { + for i := 0; i < len(x); i++ { + if y[i] < x[i] { + x[i] = y[i] + } + } +} + +func MinimumNumber_Go[T Number](x []T, a T) { + for i := 0; i < len(x); i++ { + if a < x[i] { + x[i] = a + } + } +} diff --git a/series_number.go b/series_number.go new file mode 100644 index 0000000..78e42f8 --- /dev/null +++ b/series_number.go @@ -0,0 +1,9 @@ +package pandas + +import "gitee.com/quant1x/pandas/algorithms" + +// Mean gonum.org/v1/gonum/stat不支持整型, 每次都要转换有点难受啊 +func Mean[T algorithms.Number](x []T) float64 { + d := algorithms.Mean_Go(x) + return float64(d) +} -- Gitee From 3977e386d716b6f98b2a6e1da9ec4778d4d1ff9d Mon Sep 17 00:00:00 2001 From: wangfeng Date: Tue, 31 Jan 2023 21:37:06 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fixed:=20=E4=BF=AE=E8=AE=A2=E5=A6=82?= =?UTF-8?q?=E6=9E=9Cseries=E9=95=BF=E5=BA=A6=E4=B8=BA0=E8=BF=98=E4=BC=9A?= =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E8=AE=A1=E7=AE=97=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- series_float64.go | 77 ++++++++++++++++++++++++----------------------- series_int64.go | 71 +++++++++++++++++++++++++------------------ 2 files changed, 81 insertions(+), 67 deletions(-) diff --git a/series_float64.go b/series_float64.go index a715b9b..ba7efe3 100644 --- a/series_float64.go +++ b/series_float64.go @@ -88,39 +88,39 @@ func (self *SeriesFloat64) assign(idx, size int, f float64) { } } -func (s *SeriesFloat64) Name() string { - return s.name +func (self *SeriesFloat64) Name() string { + return self.name } -func (s *SeriesFloat64) Rename(n string) { - s.lock.RLock() - defer s.lock.RUnlock() - s.name = n +func (self *SeriesFloat64) Rename(n string) { + self.lock.RLock() + defer self.lock.RUnlock() + self.name = n } // Type returns the type of data the series holds. -func (s *SeriesFloat64) Type() Type { +func (self *SeriesFloat64) Type() Type { return SERIES_TYPE_FLOAT } -func (s *SeriesFloat64) Len() int { - s.lock.RLock() - defer s.lock.RUnlock() - return len(s.Data) +func (self *SeriesFloat64) Len() int { + self.lock.RLock() + defer self.lock.RUnlock() + return len(self.Data) } -func (s *SeriesFloat64) Shift(periods int) *Series { +func (self *SeriesFloat64) Shift(periods int) *Series { var d Series - d = clone.Clone(s).(Series) + d = clone.Clone(self).(Series) return Shift[float64](&d, periods, func() float64 { return Nil2Float }) } // deprecated: 不推荐使用 -func (s *SeriesFloat64) oldShift(periods int) *Series { +func (self *SeriesFloat64) oldShift(periods int) *Series { var d Series - d = clone.Clone(s).(Series) + d = clone.Clone(self).(Series) if periods == 0 { return &d } @@ -150,66 +150,69 @@ func (s *SeriesFloat64) oldShift(periods int) *Series { } for i := range naVals { - naVals[i] = algorithms.NaN() + naVals[i] = NaN() } return &d } -func (s *SeriesFloat64) Values() any { - return s.Data +func (self *SeriesFloat64) Values() any { + return self.Data } -func (s *SeriesFloat64) Repeat(x any, repeats int) *Series { +func (self *SeriesFloat64) Repeat(x any, repeats int) *Series { a := AnyToFloat64(x) //data := avx2.Repeat(a, repeats) data := Repeat(a, repeats) var d Series - d = NewSeriesFloat64(s.name, data) + d = NewSeriesFloat64(self.name, data) return &d } // Empty returns an empty Series of the same type -func (s *SeriesFloat64) Empty() Series { - return NewSeriesFloat64(s.name, []float64{}) +func (self *SeriesFloat64) Empty() Series { + return NewSeriesFloat64(self.name, []float64{}) } // Records returns the elements of a Series as a []string -func (s *SeriesFloat64) Records() []string { - ret := make([]string, s.Len()) - for i := 0; i < s.Len(); i++ { - //e := s.elements.Elem(i) - e := s.Data[i] +func (self *SeriesFloat64) Records() []string { + ret := make([]string, self.Len()) + for i := 0; i < self.Len(); i++ { + //e := self.elements.Elem(i) + e := self.Data[i] ret[i] = float2String(e) } return ret } -func (s *SeriesFloat64) Subset(start, end int) *Series { +func (self *SeriesFloat64) Subset(start, end int) *Series { var d Series - d = NewSeriesFloat64(s.name, s.Data[start:end]) + d = NewSeriesFloat64(self.name, self.Data[start:end]) return &d } // Rolling creates new RollingWindow -func (s *SeriesFloat64) Rolling(window int) RollingWindow { +func (self *SeriesFloat64) Rolling(window int) RollingWindow { return RollingWindow{ window: window, - series: s, + series: self, } } // Mean calculates the average value of a series -func (s *SeriesFloat64) Mean() float64 { - if s.Len() < 1 { - return algorithms.NaN() +func (self *SeriesFloat64) Mean() float64 { + if self.Len() < 1 { + return NaN() } - stdDev := avx2.Mean(s.Data) + stdDev := avx2.Mean(self.Data) return stdDev } -func (s *SeriesFloat64) StdDev() float64 { - values := s.Values().([]float64) +func (self *SeriesFloat64) StdDev() float64 { + if self.Len() < 1 { + return NaN() + } + values := self.Values().([]float64) stdDev := stat.StdDev(values, nil) return stdDev } diff --git a/series_int64.go b/series_int64.go index 87e3f72..f1f80ea 100644 --- a/series_int64.go +++ b/series_int64.go @@ -77,8 +77,8 @@ func NewSeriesInt64(name string, vals ...interface{}) *SeriesInt64 { } func (self *SeriesInt64) assign(idx, size int, n int64) { - //if StringIsNaN(s) { - // s = StringNaN + //if StringIsNaN(self) { + // self = StringNaN // self.nilCount++ //} if idx < size { @@ -88,45 +88,45 @@ func (self *SeriesInt64) assign(idx, size int, n int64) { } } -func (s *SeriesInt64) Name() string { - return s.name +func (self *SeriesInt64) Name() string { + return self.name } -func (s *SeriesInt64) Rename(n string) { - s.name = n +func (self *SeriesInt64) Rename(n string) { + self.name = n } -func (s *SeriesInt64) Type() Type { +func (self *SeriesInt64) Type() Type { return SERIES_TYPE_INT } -func (s *SeriesInt64) Shift(periods int) *Series { +func (self *SeriesInt64) Shift(periods int) *Series { var d Series - d = clone.Clone(s).(Series) + d = clone.Clone(self).(Series) return Shift[int64](&d, periods, func() int64 { return IntNaN }) } -func (s *SeriesInt64) Len() int { - s.lock.RLock() - defer s.lock.RUnlock() - return len(s.Data) +func (self *SeriesInt64) Len() int { + self.lock.RLock() + defer self.lock.RUnlock() + return len(self.Data) } -func (s *SeriesInt64) Values() any { - return s.Data +func (self *SeriesInt64) Values() any { + return self.Data } -func (s *SeriesInt64) Repeat(x any, repeats int) *Series { +func (self *SeriesInt64) Repeat(x any, repeats int) *Series { a := AnyToFloat64(x) data := Repeat(a, repeats) var d Series - d = NewSeriesInt64(s.name, data) + d = NewSeriesInt64(self.name, data) return &d } -func (s *SeriesInt64) Rolling(window int) RollingWindow { +func (self *SeriesInt64) Rolling(window int) RollingWindow { //TODO implement me panic("implement me") } @@ -136,28 +136,39 @@ func (self *SeriesInt64) Empty() Series { } // Records returns the elements of a Series as a []string -func (s *SeriesInt64) Records() []string { - ret := make([]string, s.Len()) - for i := 0; i < s.Len(); i++ { - e := s.Data[i] +func (self *SeriesInt64) Records() []string { + ret := make([]string, self.Len()) + for i := 0; i < self.Len(); i++ { + e := self.Data[i] ret[i] = int2String(e) } return ret } -func (s *SeriesInt64) Subset(start, end int) *Series { +func (self *SeriesInt64) Subset(start, end int) *Series { var d Series - d = NewSeriesInt64(s.name, s.Data[start:end]) + d = NewSeriesInt64(self.name, self.Data[start:end]) return &d } -func (s *SeriesInt64) Mean() float64 { - //TODO implement me - panic("implement me") +func (self *SeriesInt64) Mean() float64 { + if self.Len() < 1 { + return NaN() + } + stdDev := Mean(self.Data) + return stdDev } -func (s *SeriesInt64) StdDev() float64 { - values := s.Values().([]float64) - stdDev := stat.StdDev(values, nil) +func (self *SeriesInt64) StdDev() float64 { + if self.Len() < 1 { + return NaN() + } + // TODO: 每次都需要转换一次, 有没有什么好办法优化? + d := make([]float64, self.Len()) + for i := 0; i < len(d); i++ { + d[i] = float64(self.Data[i]) + } + //values := self.Values().([]int64) + stdDev := stat.StdDev(d, nil) return stdDev } -- Gitee