├── .gitignore ├── README.md └── dataframe ├── helpers.go ├── series_test.go ├── dataframe_test.go ├── element_test.go ├── series.go ├── dataframe.go └── element.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | GoBackTest.iml 3 | out/ 4 | test/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GoDataframe 2 | just like pandas in python, I want to give a quick impl in go lang for my backtest strategy system. 3 | 4 | 5 | 前因后果: 6 | 7 | 有人用过 python里面的 pandas 吗?好用不必多说。没用过的, 这篇也没什么值得看的。 8 | 9 | 我用python写的BT运行速度有点慢, 想用其他语言重写,没想到捅了马蜂窝,真是无折腾不生活。 10 | 11 | C/C++一直没正经用过,代码看、改没问题,但是要拿起来重新写个什么,感觉掌握起来有难度,只是想想,就放弃了。 12 | 13 | java虽是是本行,但感觉做这个太重了,有VM,运行环境要求太多。 14 | 15 | 后来看了下julia,号称 high-level, high-performance dynamic programming ,专为HPC而开发的类python语言, 简单写了个for, 发现与go,c相比还是有些慢, 而且版本还没1.0, 遂从入门到放弃,哎,等到长发及腰再说吧。 16 | 17 | 而后又看 rust,号称代替C++的,网上评价性能很好,不过我看到里面C++类似的语法, :: 还有 extern, 感觉迎面突然遇到了c++,不会很短时间就能搞的定(竟然发现let,感觉很惊喜),版本1.1也才刚刚开始,还是绕路吧。 18 | 19 | 选go来自一个量友的推荐, 一开始对带vm的有点担心的,毕竟stw太亮了,可是本着 “实测优先”的专业人士的思维方式,小试了一下for, 发觉性能还可以,和c一个数量级,语法掌握起来也挺快。 20 | 21 | 于是舍弃了休息时间,代码连抄带改,这个一定要说, 毕竟抄了很多github.com\kniren\gota里面的代码,不过更多的是搜一些简单语法知识,比如数字转字符,字符转数字等,从2016年11月11号,人家都在抢枪抢、买买买,我却除了想写的程序,没有想买的东西。到今天16号早上出门前,终于做了一个go的 dataframe,能够读取csv文件, 打印dataframe内容,读取df里面的Series, 有 loc函数,基本算是小成了,后面怎么改,又需要“实测优先”了。 22 | 23 | 里面没什么精雕细琢,本来才学的go,一开始连语法都不会,设计更没有细想,好在test还有点,以后重构也方便。 24 | 25 | 接下来要不要改成全部传址?这样内存占用“可能”少点,用传值还是传址, 哪个性能最好,也需要实测才行。 26 | 27 | 或者设计也可以改? 总之,想要代替pandas,要做的太多了。 28 | 29 | 而且lapack、blas也都需要看一下,是不是像pandas调用numpy一样,把go里面的底层处理换了更合适呢,想想头大。 30 | 31 | 可是,我不是为了要写类库才干这个啊。 我有正事啊。 32 | 33 | 本来在 bitbucket上的私有项目, 现在放在github上开源了, 想请人参与一下,共同改进。 34 | 35 | 独乐乐不如众乐乐。 36 | 37 | 大家一起来happy吧! 38 | 39 | 40 | 开源协议不选了。代码随便使用,无需签我名字。 41 | 42 | 李炳辰 43 | 2016-11-16日 44 | 45 | 今晚上传代码,写完描述,不写代码了, 早点休息。 46 | 47 | 48 | -------------------------------------------------------------------------------- /dataframe/helpers.go: -------------------------------------------------------------------------------- 1 | package dataframe 2 | 3 | import ( 4 | "errors" 5 | "math" 6 | "strconv" 7 | "strings" 8 | "unicode/utf8" 9 | ) 10 | 11 | // .T 12 | func TransposeRecords(x [][]string) [][]string { 13 | n := len(x) 14 | if n == 0 { 15 | return x 16 | } 17 | m := len(x[0]) 18 | y := make([][]string, m) 19 | for i := 0; i < m; i++ { 20 | z := make([]string, n) 21 | for j := 0; j < n; j++ { 22 | z[j] = x[j][i] 23 | } 24 | y[i] = z 25 | } 26 | return y 27 | } 28 | 29 | func AddRightPadding(s string, nchar int) string { 30 | if utf8.RuneCountInString(s) < nchar { 31 | return s + strings.Repeat(" ", nchar-utf8.RuneCountInString(s)) 32 | } 33 | return s 34 | } 35 | 36 | func AddLeftPadding(s string, nchar int) string { 37 | if utf8.RuneCountInString(s) < nchar { 38 | return strings.Repeat(" ", nchar-utf8.RuneCountInString(s)) + s 39 | } 40 | return s 41 | } 42 | 43 | func FindType(arr []string) string { 44 | hasFloats := false 45 | hasInts := false 46 | hasBools := false 47 | hasStrings := false 48 | for _, str := range arr { 49 | if _, err := strconv.Atoi(str); err == nil { 50 | hasInts = true 51 | continue 52 | } 53 | if _, err := strconv.ParseFloat(str, 64); err == nil { 54 | hasFloats = true 55 | continue 56 | } 57 | if str == "true" || str == "false" { 58 | hasBools = true 59 | continue 60 | } 61 | if str == "" || str == "NA" { 62 | continue 63 | } 64 | hasStrings = true 65 | } 66 | if hasFloats && !hasBools && !hasStrings { 67 | return "float" 68 | } 69 | if hasInts && !hasFloats && !hasBools && !hasStrings { 70 | return "int" 71 | } 72 | if !hasInts && !hasFloats && hasBools && !hasStrings { 73 | return "bool" 74 | } 75 | return "string" 76 | } 77 | 78 | func Range(start, end int) []int { 79 | if start > end { 80 | start, end = end, start 81 | } 82 | var arr []int 83 | for i := start; i <= end; i++ { 84 | arr = append(arr, i) 85 | } 86 | return arr 87 | } 88 | 89 | func Seq(start, end, step int) []int { 90 | if start > end { 91 | start, end = end, start 92 | } 93 | if step == 0 { 94 | return []int{} 95 | } 96 | var arr []int 97 | if step < 0 { 98 | step = int(math.Abs(float64(step))) 99 | for i := end; i >= start; i = i - step { 100 | arr = append(arr, i) 101 | } 102 | return arr 103 | } else { 104 | for i := start; i <= end; i = i + step { 105 | arr = append(arr, i) 106 | } 107 | return arr 108 | } 109 | } 110 | 111 | func OrOfBool(a []bool, b []bool) ([]bool, error) { 112 | if len(a) != len(b) { 113 | return nil, errors.New("Different lengths") 114 | } 115 | ret := make([]bool, len(a), len(a)) 116 | for i := 0; i < len(a); i++ { 117 | ret[i] = a[i] || b[i] 118 | } 119 | return ret, nil 120 | } 121 | 122 | func IsInIntSlice(i int, is []int) bool { 123 | for _, v := range is { 124 | if v == i { 125 | return true 126 | } 127 | } 128 | return false 129 | } 130 | -------------------------------------------------------------------------------- /dataframe/series_test.go: -------------------------------------------------------------------------------- 1 | package dataframe 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | func TestCreate_series(t *testing.T) { 10 | var se Series = Strings([]string{"A", "B", "", "1", "2", "true", "false", "123456.01", "78.9", "2016-01-01", "2016-12-31"}) 11 | fmt.Printf("%s\n", se) 12 | 13 | se = Ints([]int{123456, 678, 789}) 14 | fmt.Printf("%s\n", se) 15 | 16 | se = Floats([]float64{123456.01, 56.7, 78.9}) 17 | fmt.Printf("%s\n", se) 18 | 19 | se = Bools([]bool{true, true, false}) 20 | fmt.Printf("%s\n", se) 21 | 22 | se = Times("2006-01-02", []string{"2016-01-02", "2016-12-12", "2016-12-11"}) 23 | fmt.Printf("%s\n", se) 24 | } 25 | 26 | func TestCreate_named_series(t *testing.T) { 27 | var se Series = NamedStrings("nameABC", []string{"A", "B", "", "1", "2", "true", "false", "123456.01", "78.9", "2016-01-01", "2016-12-31"}) 28 | fmt.Printf("string of Series is: %s\n", se) 29 | 30 | se = NamedInts("name1", []int{123456, 678, 789, 90}) 31 | fmt.Printf("string of Series is: %s\n", se) 32 | 33 | se = NamedFloats("name1", []float64{123456.01, 56.7, 78.9}) 34 | fmt.Printf("%s string of Series is: %s\n", se, se) 35 | 36 | se = NamedBools("name1", []bool{true, true, false, true, true, false}) 37 | fmt.Printf("%s string of Series is: %s\n", se, se) 38 | 39 | se = NamedTimes("name1", "2006-01-02", []string{"2016-01-01", "2016-12-12", "2016-12-29"}) 40 | fmt.Printf("%s string of Series is: %s\n", se, se) 41 | } 42 | 43 | func TestCreate_named_series_value(t *testing.T) { 44 | var se Series = NamedStrings("nameABC", []string{"A", "B", "", "1", "2", "true", "false", "123456.01", "78.9", "2016-01-01", "2016-12-31"}) 45 | fmt.Printf("%s type=%s length=%d \n", se, se.Type(), Len(se)) 46 | for i, v := range Values(se) { 47 | fmt.Printf("%d, %s\n", i, v) 48 | } 49 | 50 | se = NamedInts("name1", []int{123456, 678, 789}) 51 | fmt.Printf("%s type=%s length=%d \n", se, se.Type(), Len(se)) 52 | for i, v := range Values(se) { 53 | fmt.Printf("%d, %s\n", i, v) 54 | } 55 | 56 | se = NamedFloats("name1", []float64{123456.01, 56.7, 78.9}) 57 | fmt.Printf("%s type=%s length=%d \n", se, se.Type(), Len(se)) 58 | for i, v := range Values(se) { 59 | fmt.Printf("%d, %s\n", i, v) 60 | } 61 | 62 | se = NamedBools("name1", []bool{true, true, false}) 63 | fmt.Printf("%s type=%s length=%d \n", se, se.Type(), Len(se)) 64 | for i, v := range Values(se) { 65 | fmt.Printf("%d, %s\n", i, v) 66 | } 67 | 68 | se = NamedTimes("name1", "2006-01-02", []string{"2016-01-01", "2016-12-12", "2016-12-11"}) 69 | fmt.Printf("%s type=%s length=%d \n", se, se.Type(), Len(se)) 70 | for i, v := range Values(se) { 71 | fmt.Printf("%d, %s\n", i, v) 72 | } 73 | } 74 | 75 | func TestSet_Index_series(t *testing.T) { 76 | var se Series = NamedStrings("nameABC", []string{"A", "B", "", "1", "2", "true", "false", "123456.01", "78.9", "2016-01-01", "2016-12-31"}) 77 | fmt.Printf("%s string of Series is: %s\n", se, se) 78 | for i, v := range Values(se) { 79 | fmt.Printf("%d, %s\n", i, v) 80 | } 81 | val := Values(se) 82 | se.setIndex(&val) 83 | 84 | fmt.Printf("%s string of Series is: %s\n", se, se) 85 | } 86 | 87 | func TestSet_Index_shift(t *testing.T) { 88 | var se Series = NamedStrings("nameABC", []string{"A", "B", "", "1", "2", "true", "false", "123456.01", "78.9", "2016-01-01", "2016-12-31"}) 89 | for i, v := range Values(se) { 90 | fmt.Printf("%d, %s\n", i, v) 91 | } 92 | se.shift(1) 93 | fmt.Printf("after shift \n") 94 | for i, v := range Values(se) { 95 | fmt.Printf("%d, %s\n", i, v) 96 | } 97 | } 98 | 99 | func TestSet_IndexOf_series(t *testing.T) { 100 | var se Series = NamedStrings("nameABC", []string{"A", "B", "", "1", "2", "true", "false", "123456.01", "78.9", "2016-01-01", "2016-12-31"}) 101 | fmt.Printf("%s string of Series is: %s\n", se, se) 102 | 103 | val := Values(se) 104 | se.setIndex(&val) 105 | 106 | fmt.Printf("%s string of Series is: %s\n", se, se) 107 | 108 | x, _ := ToString(se.indexOf(0)) 109 | fmt.Printf("indexOf(0) of Series is: %s\n", x) 110 | if !strings.EqualFold(*x.s, "A") { 111 | t.Error("not match") 112 | t.Fail() 113 | } 114 | 115 | xy, _ := ToString(se.indexOf(3)) 116 | 117 | fmt.Printf("indexOf(3) of Series is: %s\n", xy) 118 | if !strings.EqualFold(*xy.s, "1") { 119 | t.Error("not match") 120 | t.Fail() 121 | } 122 | 123 | st := "123456.01" 124 | xy, _ = ToString(se.loc(stringElement{&st})) 125 | 126 | fmt.Printf("loc of Series is: %s\n", xy) 127 | if !strings.EqualFold(*xy.s, "123456.01") { 128 | t.Error("not match") 129 | t.Fail() 130 | } 131 | 132 | } 133 | 134 | func TestSet_order_series(t *testing.T) { 135 | var se Series = NamedStrings("nameABC", []string{"A", "B", "C", "DE", "fg", "1", "2", "34", "56", "35", "BB"}) 136 | fmt.Printf("%s string of Series is: %s\n", se, se) 137 | 138 | val := Values(se) 139 | se.setIndex(&val) 140 | 141 | fmt.Printf("%s string of Series is: %s\n", se, se) 142 | 143 | sasc := se.Sort_indexASC() 144 | fmt.Printf("%s string of Series is: %s\n", *sasc, *sasc) 145 | sdesc := se.Sort_indexDESC() 146 | fmt.Printf("%s string of Series is: %s\n", *sdesc, *sdesc) 147 | 148 | } 149 | -------------------------------------------------------------------------------- /dataframe/dataframe_test.go: -------------------------------------------------------------------------------- 1 | package dataframe 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | const stock_file_add string = "C:\\GOPATH\\src\\GoBackTest\\test\\data\\000006.csv" 9 | 10 | func TestRead_csv(t *testing.T) { 11 | //fmt.Printf("running %s\n", "Read_csv") 12 | csvFormat := CsvPaserFormatter{} 13 | 14 | csvFormat.CsvFilePath = stock_file_add 15 | csvFormat.Index_col = 0 16 | csvFormat.Parse_dates = 0 17 | //dont need to paser date column 18 | csvFormat.Date_paser_format = "2006-01-02" 19 | csvFormat.Skiprows = 1 20 | 21 | //fmt.Printf("a file: %s\n", *csvFormat.csvFilePath) 22 | 23 | df, err := Read_csv(csvFormat) 24 | if err != nil { 25 | t.Errorf("read csv file error %v\n", err) 26 | t.FailNow() 27 | } 28 | 29 | fmt.Printf("\n%s", df) 30 | } 31 | 32 | func Test_Column(test *testing.T) { 33 | //fmt.Printf("running %s\n", "Read_csv") 34 | csvFormat := CsvPaserFormatter{} 35 | 36 | csvFormat.CsvFilePath = stock_file_add 37 | csvFormat.Index_col = 0 38 | csvFormat.Parse_dates = 0 39 | //dont need to paser date column 40 | csvFormat.Date_paser_format = "2006-01-02" 41 | csvFormat.Skiprows = 1 42 | 43 | //fmt.Printf("a file: %s\n", *csvFormat.csvFilePath) 44 | 45 | df, err := Read_csv(csvFormat) 46 | if err != nil { 47 | test.Errorf("read csv file error %v\n", err) 48 | test.FailNow() 49 | } 50 | fmt.Printf("\n%s", df) 51 | 52 | shape := df.shape() 53 | if shape[0] < 0 || shape[1] < 0 { 54 | test.Errorf("shape error %s\n", shape) 55 | test.FailNow() 56 | } 57 | 58 | if se, err := df.column("open"); err == nil { 59 | if len(Values(se)) < 10 { 60 | test.Errorf("df.column(\"open\") get error\n") 61 | test.FailNow() 62 | } else { 63 | fmt.Printf("%s", se) 64 | } 65 | 66 | } else { 67 | test.Errorf("df.column(\"open\") get error\n", err) 68 | test.FailNow() 69 | } 70 | 71 | if _, err := df.column("highX"); err == nil { 72 | test.Errorf("df.column(\"highX\") should has error\n") 73 | test.FailNow() 74 | } 75 | 76 | m2 := df.indexOf(12) 77 | if m2 == nil { 78 | test.Errorf("should has value\n") 79 | test.FailNow() 80 | } 81 | fmt.Printf("%s", m2) 82 | fmt.Printf("%s", df.IndexType) 83 | 84 | } 85 | 86 | func Test_loc(test *testing.T) { 87 | //fmt.Printf("running %s\n", "Read_csv") 88 | csvFormat := CsvPaserFormatter{} 89 | 90 | csvFormat.CsvFilePath = stock_file_add 91 | csvFormat.Index_col = 0 92 | csvFormat.Parse_dates = 0 93 | //dont need to paser date column 94 | csvFormat.Date_paser_format = "2006-01-02" 95 | csvFormat.Skiprows = 1 96 | 97 | //fmt.Printf("a file: %s\n", *csvFormat.csvFilePath) 98 | 99 | df, err := Read_csv(csvFormat) 100 | if err != nil { 101 | test.Errorf("read csv file error %v\n", err) 102 | test.FailNow() 103 | } 104 | //fmt.Printf("\n%s", df) 105 | strOftime := "2010-11-03 00:00:00" 106 | if result, err := createTimeElement("2006-01-02 15:04:05", &strOftime); err != nil { 107 | test.Errorf("createTimeElement error", err) 108 | test.Fail() 109 | } else { 110 | 111 | fmt.Printf("%s\n", result) 112 | m2 := df.loc(result) 113 | 114 | fmt.Printf("%s", m2) 115 | 116 | if m2 == nil { 117 | test.Errorf("should has loc value\n") 118 | test.FailNow() 119 | } 120 | 121 | floatVal := 3.79 122 | floatE := floatElement{&floatVal} 123 | if !Eq(m2["open"], floatE) { 124 | test.Errorf("get the wrong loc value\n") 125 | test.FailNow() 126 | } 127 | 128 | floatVal = 3.86 129 | floatE = floatElement{&floatVal} 130 | if !Eq(m2["high"], floatE) { 131 | test.Errorf("get the wrong loc value\n") 132 | test.FailNow() 133 | } 134 | 135 | floatVal = 3.81 136 | floatE = floatElement{&floatVal} 137 | if !Eq(m2["close"], floatE) { 138 | test.Errorf("get the wrong loc value\n") 139 | test.FailNow() 140 | } 141 | 142 | floatVal = 3.74 143 | floatE = floatElement{&floatVal} 144 | if !Eq(m2["low"], floatE) { 145 | test.Errorf("get the wrong loc value\n") 146 | test.FailNow() 147 | } 148 | 149 | floatVal = 13722173.00 150 | floatE = floatElement{&floatVal} 151 | if !Eq(m2["volume"], floatE) { 152 | test.Errorf("get the wrong loc value\n") 153 | test.FailNow() 154 | } 155 | 156 | floatVal = 102153632.00 157 | floatE = floatElement{&floatVal} 158 | if !Eq(m2["amount"], floatE) { 159 | test.Errorf("get the wrong loc value\n") 160 | test.FailNow() 161 | } 162 | 163 | //date open high close low volume amount 164 | // 2010-11-03 00:00:00 +0000 UTC 3.79 3.86 3.81 3.74 13722173.00 102153632.00 165 | 166 | } 167 | } 168 | 169 | func Test_ReferenceByAddress(test *testing.T) { 170 | 171 | //fmt.Printf("running %s\n", "Read_csv") 172 | csvFormat := CsvPaserFormatter{} 173 | 174 | csvFormat.CsvFilePath = stock_file_add 175 | csvFormat.Index_col = 0 176 | csvFormat.Parse_dates = 0 177 | //dont need to paser date column 178 | csvFormat.Date_paser_format = "2006-01-02" 179 | csvFormat.Skiprows = 1 180 | 181 | //fmt.Printf("a file: %s\n", *csvFormat.csvFilePath) 182 | 183 | df, err := Read_csv(csvFormat) 184 | if err != nil { 185 | test.Errorf("read csv file error %v\n", err) 186 | test.FailNow() 187 | } 188 | fmt.Printf("for check the rederence by address manuelly :\n%s", df) 189 | fmt.Printf("the address of df Index:%p\n", df.Index) 190 | seriesList := df.columns 191 | 192 | for i := 0; i < len(seriesList); i++ { 193 | s := seriesList[i] 194 | fmt.Printf("the address of Series Index:%p\n", s.Index) 195 | fmt.Printf("the address of Series values:%p\n", s.values) 196 | } 197 | 198 | } 199 | 200 | func Test_Head_and_tail(test *testing.T) { 201 | 202 | //fmt.Printf("running %s\n", "Read_csv") 203 | csvFormat := CsvPaserFormatter{} 204 | 205 | csvFormat.CsvFilePath = stock_file_add 206 | csvFormat.Index_col = 0 207 | csvFormat.Parse_dates = 0 208 | //dont need to paser date column 209 | csvFormat.Date_paser_format = "2006-01-02" 210 | csvFormat.Skiprows = 1 211 | 212 | //fmt.Printf("a file: %s\n", *csvFormat.csvFilePath) 213 | 214 | df, err := Read_csv(csvFormat) 215 | if err != nil { 216 | test.Errorf("read csv file error %v\n", err) 217 | test.FailNow() 218 | } 219 | 220 | fmt.Printf("print tail :\n%s", df.tail()) 221 | 222 | fmt.Printf("print tailOf(30) :\n%s", df.tailOf(30)) 223 | 224 | fmt.Printf("print head :\n%s", df.head()) 225 | 226 | fmt.Printf("print headOf(30) :\n%s", df.headOf(30)) 227 | 228 | } 229 | -------------------------------------------------------------------------------- /dataframe/element_test.go: -------------------------------------------------------------------------------- 1 | package dataframe 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | func TestCreate_element(t *testing.T) { 11 | str := stringElement{} 12 | aString := "abc" 13 | str.s = &aString 14 | fmt.Printf("%s\n", str) 15 | if str.String() != "abc" { 16 | t.Errorf("string is not same") 17 | t.Fail() 18 | } 19 | 20 | inte := intElement{} 21 | integ := 789 22 | inte.i = &integ 23 | fmt.Printf("%s\n", inte) 24 | if inte.String() != "789" { 25 | t.Errorf("int is not same") 26 | t.Fail() 27 | } 28 | 29 | flo := floatElement{} 30 | floa := 89.098 31 | flo.f = &floa 32 | fmt.Printf("%.3f\n", *flo.f) 33 | fmt.Printf("%v\n", flo) 34 | 35 | //%.2f is the default format 36 | if flo.String() != "89.10" { 37 | t.Errorf("float is not same") 38 | t.Fail() 39 | } 40 | 41 | bol := boolElement{} 42 | bole := true 43 | bol.b = &bole 44 | fmt.Printf("%s\n", bol) 45 | if bol.String() != "true" { 46 | t.Errorf("bool is not same") 47 | t.Fail() 48 | } 49 | 50 | tim := timeElement{} 51 | tim1 := time.Now() 52 | tim.t = &tim1 53 | fmt.Printf("%v\n", tim) 54 | fmt.Printf("%v\n", tim.t) 55 | fmt.Printf("%v\n", *tim.t) 56 | 57 | strOfTime := fmt.Sprintf("%v", *tim.t) 58 | if !strings.EqualFold(tim.String(), strOfTime) { 59 | t.Errorf("time is not same") 60 | t.Fail() 61 | } 62 | } 63 | 64 | func TestToString_element(test *testing.T) { 65 | 66 | aString := "abc" 67 | str := stringElement{&aString} 68 | 69 | fmt.Printf("%s\n", str) 70 | if str.String() != "abc" { 71 | test.Errorf("string is not same") 72 | test.Fail() 73 | } 74 | 75 | fmt.Printf("length of string:%d\n", str.Len()) 76 | 77 | inte := intElement{} 78 | integ := 789 79 | inte.i = &integ 80 | fmt.Printf("%s\n", inte) 81 | if inte.String() != "789" { 82 | test.Errorf("int is not same") 83 | test.Fail() 84 | } 85 | //convert to stringElement 86 | vStr, _ := ToString(inte) 87 | fmt.Printf("type of int:%v\n", vStr) 88 | fmt.Printf("length of int:%d\n", vStr.Len()) 89 | 90 | flo := floatElement{} 91 | floa := 89.098 92 | flo.f = &floa 93 | fmt.Printf("%.3f\n", *flo.f) 94 | fmt.Printf("%v\n", flo) 95 | 96 | //%.2f is the default format 97 | if flo.String() != "89.10" { 98 | test.Errorf("float is not same") 99 | test.Fail() 100 | } 101 | //convert to stringElement 102 | vStr, _ = ToString(flo) 103 | fmt.Printf("type of flo:%v\n", vStr) 104 | fmt.Printf("length of flo:%d\n", vStr.Len()) 105 | if !strings.EqualFold(*vStr.s, "89.10") { 106 | test.Errorf("float is not same") 107 | test.Fail() 108 | } 109 | 110 | bol := boolElement{} 111 | bole := true 112 | bol.b = &bole 113 | fmt.Printf("%s\n", bol) 114 | if bol.String() != "true" { 115 | test.Errorf("bool is not same") 116 | test.Fail() 117 | } 118 | //convert to stringElement 119 | vStr, _ = ToString(bol) 120 | fmt.Printf("type of bool:%v\n", vStr) 121 | fmt.Printf("length of bool:%d\n", vStr.Len()) 122 | if !strings.EqualFold(*vStr.s, "true") { 123 | test.Errorf("float is not same") 124 | test.Fail() 125 | } 126 | 127 | tim := timeElement{} 128 | tim1 := time.Now() 129 | tim.t = &tim1 130 | fmt.Printf("%v\n", tim) 131 | fmt.Printf("%v\n", tim.t) 132 | fmt.Printf("%v\n", *tim.t) 133 | 134 | strOfTime := fmt.Sprintf("%v", *tim.t) 135 | 136 | if !strings.EqualFold(tim.String(), strOfTime) { 137 | test.Errorf("time is not same") 138 | test.Fail() 139 | } 140 | 141 | //convert to stringElement 142 | vStr, _ = ToString(tim) 143 | 144 | fmt.Printf("length of time:%d\n", vStr.Len()) 145 | fmt.Printf("length of time:%d\n", len(strOfTime)) 146 | if vStr.Len() != len(strOfTime) { 147 | test.Errorf("time is not same") 148 | test.Fail() 149 | 150 | } 151 | fmt.Printf("type of time:[%v]\n", strOfTime) 152 | fmt.Printf("type of time:[%v]\n", tim.String()) 153 | 154 | if !strings.EqualFold(tim.String(), strOfTime) { 155 | test.Errorf("time is not same") 156 | test.Fail() 157 | } 158 | } 159 | 160 | func TestTime_element(test *testing.T) { 161 | //could not paser other format 162 | aformat_timeElement_style1 := "2006-01-02 15:04:05" 163 | 164 | if result, err := createTimeElement("2006-01-02 15:04:05", &aformat_timeElement_style1); err != nil { 165 | test.Errorf("createTimeElement error", err) 166 | test.Fail() 167 | } else { 168 | fmt.Printf("%s\n", result) 169 | } 170 | 171 | aformat_timeElement_style1 = "2016-11-10 15:16:17" 172 | if result, err := createTimeElement("2006-01-02 15:04:05", &aformat_timeElement_style1); err != nil { 173 | test.Errorf("createTimeElement error", err) 174 | test.Fail() 175 | } else { 176 | fmt.Printf("%s\n", result) 177 | } 178 | 179 | aformat_timeElement_style1 = "2016-12-12" 180 | if result, err := createTimeElement("2006-01-02", &aformat_timeElement_style1); err != nil { 181 | test.Errorf("createTimeElement error", err) 182 | test.Fail() 183 | } else { 184 | fmt.Printf("%s\n", result) 185 | } 186 | aformat_timeElement_style2 := "20160103190208" 187 | if result, err := createTimeElement("20060102150405", &aformat_timeElement_style2); err != nil { 188 | test.Errorf("createTimeElement error", err) 189 | test.Fail() 190 | } else { 191 | fmt.Printf("%s\n", result) 192 | } 193 | aformat_timeElement_style3 := "2016/11/23 19:02:08" 194 | if result, err := createTimeElement("2006/01/02 15:04:05", &aformat_timeElement_style3); err != nil { 195 | test.Errorf("createTimeElement error", err) 196 | test.Fail() 197 | } else { 198 | fmt.Printf("%s\n", result) 199 | } 200 | aformat_timeElement_style4 := "2016/10/23" 201 | if result, err := createTimeElement("2006/01/02", &aformat_timeElement_style4); err != nil { 202 | test.Errorf("createTimeElement error", err) 203 | test.Fail() 204 | } else { 205 | fmt.Printf("%s\n", result) 206 | } 207 | 208 | aformat_timeElement_style5 := "20160105" 209 | if result, err := createTimeElement("20060102", &aformat_timeElement_style5); err != nil { 210 | test.Errorf("createTimeElement error", err) 211 | test.Fail() 212 | } else { 213 | fmt.Printf("%s\n", result) 214 | } 215 | 216 | } 217 | func TestTime_element_eq(test *testing.T) { 218 | //could not paser other format 219 | aformat_timeElement_style1 := "2006-01-02 15:04:05" 220 | str1 := stringElement{&aformat_timeElement_style1} 221 | str2 := stringElement{&aformat_timeElement_style1} 222 | if !str1.Eq(str2) { 223 | test.Errorf("stringElement should same!") 224 | test.Fail() 225 | } 226 | 227 | if !Eq(str1, str2) { 228 | test.Errorf("stringElement should same!") 229 | test.Fail() 230 | } 231 | 232 | intE := 2006 233 | intEle := intElement{&intE} 234 | if Eq(intEle, str2) { 235 | test.Errorf("stringElement,intElement should not same!") 236 | test.Fail() 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /dataframe/series.go: -------------------------------------------------------------------------------- 1 | package dataframe 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | "unicode/utf8" 8 | ) 9 | 10 | const Int_type = "int" 11 | const Float_type = "float" 12 | const String_type = "string" 13 | const Bool_type = "bool" 14 | const Time_type = "time" 15 | 16 | type Series struct { 17 | Name string // The name of the series 18 | t string // The type of the series 19 | Index []elementValue // an Elements used as index 20 | values []elementValue 21 | RuneCount int 22 | } 23 | 24 | type SeriesInterface interface { 25 | Strings([]string) Series 26 | Ints([]int) Series 27 | Floats([]float64) Series 28 | Bools([]bool) Series 29 | Times(string, []string) Series 30 | 31 | NamedStrings(string, []string) Series 32 | NamedInts(string, []int) Series 33 | NamedFloats(string, []float64) Series 34 | NamedBools(string, []bool) Series 35 | NamedTimes(string, string, []string) Series 36 | 37 | Values(Series) []elementValue 38 | String(Series) string 39 | Len(Series) int 40 | Type() string 41 | 42 | setIndex(*Series, *[]elementValue) Series 43 | 44 | sort_indexASC() *Series 45 | sort_indexDESC() *Series 46 | shift(int) SeriesInterface 47 | indexOf(int) elementValue //get a row of Series, -1 is the last row 48 | loc(elementValue) elementValue //get a row of Series, elementValue is the index value 49 | 50 | //add(Series) Series 51 | //subtract(Series) Series 52 | //multiply(Series) Series 53 | //divide(Series) Series 54 | // 55 | //add(int) Series 56 | //subtract(int) Series 57 | //multiply(int) Series 58 | //divide(int) Series 59 | // 60 | //add(float64) Series 61 | //subtract(float64) Series 62 | //multiply(float64) Series 63 | //divide(float64) Series 64 | } 65 | 66 | func (s *Series) setValues(values *[]elementValue) { 67 | s.values = *values 68 | var RuneCount int 69 | for _, v := range *values { 70 | if stringElement, error := ToString(v); error == nil { 71 | count := utf8.RuneCountInString(*stringElement.s) 72 | if count > RuneCount { 73 | RuneCount = count 74 | } 75 | } 76 | } 77 | s.RuneCount = RuneCount 78 | } 79 | 80 | func (s *Series) setIndex(index *[]elementValue) { 81 | s.Index = *index 82 | } 83 | 84 | func (s *Series) loc(val elementValue) elementValue { 85 | if len(s.Index) == 0 { 86 | var empty string = "" 87 | return stringElement{&empty} 88 | } 89 | s1, _ := ToString(val) 90 | for i := 0; i < len(s.Index); i++ { 91 | s2, _ := ToString(s.Index[i]) 92 | if strings.EqualFold(*s1.s, *s2.s) { 93 | return s.values[i] 94 | } 95 | } 96 | var empty string = "" 97 | return stringElement{&empty} 98 | } 99 | 100 | func (s *Series) indexOf(idx int) elementValue { 101 | if idx < 0 { 102 | return s.values[len(s.Index)+idx] 103 | } 104 | if len(s.Index) <= idx { 105 | var empty string = "" 106 | return stringElement{&empty} 107 | } 108 | return s.values[idx] 109 | } 110 | 111 | func (s *Series) shift(idx int) *Series { 112 | //s.values[0] = nil 113 | s.values = s.values[1:len(s.values)] 114 | return s 115 | } 116 | 117 | // Strings is a constructor for a String series 118 | func Strings(args []string) Series { 119 | var valuesArr []elementValue = make([]elementValue, len(args)) 120 | var RuneCount int 121 | for i := 0; i < len(args); i++ { 122 | valuesArr[i] = stringElement{&args[i]} 123 | count := utf8.RuneCountInString(args[i]) 124 | if count > RuneCount { 125 | RuneCount = count 126 | } 127 | } 128 | //could not use the "for i, v := range args" here 129 | //the v will change to the latest address 130 | ret := Series{ 131 | Name: "", 132 | values: valuesArr, 133 | RuneCount: RuneCount, 134 | t: String_type, 135 | } 136 | return ret 137 | } 138 | 139 | func Ints(args []int) Series { 140 | var valuesArr []elementValue = make([]elementValue, len(args)) 141 | var RuneCount int 142 | for i := 0; i < len(args); i++ { 143 | valuesArr[i] = intElement{&(args[i])} 144 | strOfInt := strconv.Itoa(args[i]) 145 | count := utf8.RuneCountInString(strOfInt) 146 | if count > RuneCount { 147 | RuneCount = count 148 | } 149 | } 150 | ret := Series{ 151 | Name: "", 152 | values: valuesArr, 153 | RuneCount: RuneCount, 154 | t: Int_type, 155 | } 156 | return ret 157 | } 158 | 159 | func Floats(args []float64) Series { 160 | var valuesArr []elementValue = make([]elementValue, len(args)) 161 | var RuneCount int 162 | for i := 0; i < len(args); i++ { 163 | valuesArr[i] = floatElement{&args[i]} 164 | strOfInt := strconv.FormatFloat(float64(args[i]), 'f', 6, 64) 165 | count := utf8.RuneCountInString(strOfInt) 166 | if count > RuneCount { 167 | RuneCount = count 168 | } 169 | } 170 | ret := Series{ 171 | Name: "", 172 | values: valuesArr, 173 | RuneCount: RuneCount, 174 | t: Float_type, 175 | } 176 | return ret 177 | } 178 | 179 | func Bools(args []bool) Series { 180 | var valuesArr []elementValue = make([]elementValue, len(args)) 181 | var RuneCount int = 4 182 | for i := 0; i < len(args); i++ { 183 | valuesArr[i] = boolElement{&args[i]} 184 | } 185 | ret := Series{ 186 | Name: "", 187 | values: valuesArr, 188 | RuneCount: RuneCount, 189 | t: Bool_type, 190 | } 191 | return ret 192 | } 193 | 194 | func Times(datetimeFormat string, args []string) Series { 195 | var valuesArr []elementValue = make([]elementValue, len(args)) 196 | var RuneCount int = len("1994-01-11 00:00:00 +0000 UTC") 197 | for i := 0; i < len(args); i++ { 198 | valuesArr[i], _ = createTimeElement(datetimeFormat, &args[i]) 199 | } 200 | ret := Series{ 201 | Name: "", 202 | values: valuesArr, 203 | RuneCount: RuneCount, 204 | t: Time_type, 205 | } 206 | return ret 207 | } 208 | 209 | // NamedStrings is a constructor for a named String series 210 | func NamedStrings(name string, args []string) Series { 211 | s := Strings(args) 212 | s.Name = name 213 | return s 214 | } 215 | 216 | // NamedInts is a constructor for a named Int series 217 | func NamedInts(name string, args []int) Series { 218 | s := Ints(args) 219 | s.Name = name 220 | return s 221 | } 222 | 223 | // NamedFloats is a constructor for a named Float series 224 | func NamedFloats(name string, args []float64) Series { 225 | s := Floats(args) 226 | s.Name = name 227 | return s 228 | } 229 | 230 | // NamedBools is a constructor for a named Bool series 231 | func NamedBools(name string, args []bool) Series { 232 | s := Bools(args) 233 | s.Name = name 234 | return s 235 | } 236 | 237 | // NamedBools is a constructor for a named Bool series 238 | func NamedTimes(name string, datetimeFormat string, args []string) Series { 239 | s := Times(datetimeFormat, args) 240 | s.Name = name 241 | return s 242 | } 243 | 244 | func Values(s Series) []elementValue { 245 | return s.values 246 | } 247 | 248 | // String implements the Stringer interface for Series 249 | func (s Series) String() string { 250 | var ret []string 251 | // If name exists print name 252 | if s.Name != "" { 253 | ret = append(ret, "\nName: "+s.Name) 254 | } 255 | ret = append(ret, "Type: "+s.t) 256 | ret = append(ret, "Length: "+fmt.Sprint(Len(s))) 257 | if Len(s) != 0 { 258 | // Get the maximum number of characters of index 259 | maxIndexChars := 0 260 | if len(s.Index) > 0 { 261 | for _, v := range s.Index { 262 | //elementValue 263 | vStr, _ := ToString(v) 264 | if vStr.Len() > maxIndexChars { 265 | maxIndexChars = utf8.RuneCountInString(*vStr.s) 266 | } 267 | } 268 | } 269 | 270 | for i, v := range s.values { 271 | var aRow string 272 | if len(s.Index) >= i+1 { 273 | //has index title of this "i" 274 | idxStr, _ := ToString(s.Index[i]) 275 | vStr, _ := ToString(v) 276 | aRow += AddLeftPadding(*idxStr.s, maxIndexChars+1) + AddLeftPadding(*vStr.s, s.RuneCount+2) //hard code 2 277 | } else { 278 | vStr, _ := ToString(v) 279 | aRow += AddLeftPadding("", maxIndexChars+1) + AddLeftPadding(*vStr.s, s.RuneCount+2) //hard code 2 280 | } 281 | ret = append(ret, aRow) 282 | } 283 | } 284 | return strings.Join(ret, "\n") 285 | } 286 | 287 | // Len returns the length of a given Series 288 | func Len(s Series) int { 289 | return (len(s.values)) 290 | } 291 | 292 | // Type returns the type of a given series 293 | func (s Series) Type() string { 294 | return s.t 295 | } 296 | 297 | func (s *Series) Sort_indexASC() *Series { 298 | return s.sort_index(true) 299 | } 300 | 301 | func (s *Series) Sort_indexDESC() *Series { 302 | return s.sort_index(false) 303 | } 304 | 305 | func (s *Series) sort_index(asc bool) *Series { 306 | if len(s.Index) == 0 { 307 | // do nothing 308 | return s 309 | } 310 | for i := 0; i < len(s.Index); i++ { 311 | for j := 0; j < len(s.Index)-1; j++ { 312 | jGreaterThanJPlus1 := false 313 | switch s.t { 314 | case Int_type: 315 | s1 := s.Index[j].(intElement) 316 | s2 := s.Index[j+1].(intElement) 317 | if s1.Greater(s2) { 318 | jGreaterThanJPlus1 = true 319 | } 320 | case Float_type: 321 | if s.Index[j].(floatElement).Greater(s.Index[j+1].(floatElement)) { 322 | jGreaterThanJPlus1 = true 323 | } 324 | case String_type: 325 | if s.Index[j].(stringElement).Greater(s.Index[j+1].(stringElement)) { 326 | jGreaterThanJPlus1 = true 327 | } 328 | case Bool_type: 329 | if s.Index[j].(boolElement).Greater(s.Index[j+1].(boolElement)) { 330 | jGreaterThanJPlus1 = true 331 | } 332 | case Time_type: 333 | if s.Index[j].(timeElement).Greater(s.Index[j+1].(timeElement)) { 334 | jGreaterThanJPlus1 = true 335 | } 336 | default: 337 | //do nothing 338 | } 339 | //s.Index[j] > s.Index[j + 1] 340 | if asc { 341 | if jGreaterThanJPlus1 { 342 | tmp := s.Index[j+1] 343 | s.Index[j+1] = s.Index[j] 344 | s.Index[j] = tmp 345 | } 346 | } else { 347 | if !jGreaterThanJPlus1 { 348 | tmp := s.Index[j+1] 349 | s.Index[j+1] = s.Index[j] 350 | s.Index[j] = tmp 351 | } 352 | } 353 | } 354 | } 355 | return s 356 | } 357 | -------------------------------------------------------------------------------- /dataframe/dataframe.go: -------------------------------------------------------------------------------- 1 | package dataframe 2 | 3 | import ( 4 | "bytes" 5 | "encoding/csv" 6 | "errors" 7 | "io" 8 | "io/ioutil" 9 | "strconv" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | type DataFrame struct { 15 | Name string 16 | columns []Series 17 | ColumnNames []string 18 | ncols int 19 | nrows int 20 | Index []elementValue // an Elements used as index 21 | IndexType string // The type of the series 22 | } 23 | 24 | type DataFrameInterface interface { 25 | filterTimeIndexByRange(time.Time, time.Time) DataFrameInterface 26 | sort_index() DataFrameInterface 27 | tailOf(int) string 28 | headOf(int) string 29 | tail() string 30 | head() string 31 | shape() []int 32 | indexOf(int) map[string]elementValue //get a row of dataframe, -1 is the last row 33 | loc(elementValue) map[string]elementValue //get a row of dataframe, elementValue is the index value 34 | column(string) Series //get the column by name 35 | 36 | //some thing about : df["sma_0"] = df["ma_" + str(shortPeriod)] 37 | //df["dvix"] = df["dprice"] / df["dprice"].shift(1) * 100 38 | //row["dprice"] <= row["sma_9"]: 39 | 40 | } 41 | 42 | var EMPTY DataFrame 43 | 44 | func init() { 45 | EMPTY = DataFrame{} 46 | } 47 | 48 | // 49 | //pd.read_csv(rss, 50 | //engine='c', 51 | //delimiter = ",", encoding="gbk", names=["date_str","hour_min","open", "high", "low", "close", "volume", "hold_amount", "adj_close"], 52 | //dtype={"date_str" : np.str,"hour_min" : np.str},skip_blank_lines=True, skiprows=2, #skipfooter=2, 53 | //error_bad_lines=True, warn_bad_lines = True) 54 | 55 | type CsvPaserFormatter struct { 56 | CsvFilePath string //point to the file path string 57 | Index_col int //indecate which is the index 58 | Parse_dates int //indecator which is a date format 59 | Date_paser_format string //indecator the date paser format 60 | Skiprows int 61 | Skipfooter int 62 | } 63 | 64 | func sort_index() DataFrame { 65 | return DataFrame{} 66 | } 67 | 68 | func New(series ...Series) DataFrame { 69 | return DataFrame{} 70 | } 71 | 72 | func (df DataFrame) shape() []int { 73 | return []int{df.nrows, df.ncols} 74 | } 75 | 76 | func (df DataFrame) loc(eleValue elementValue) map[string]elementValue { 77 | for i, v := range df.Index { 78 | if Eq(v, eleValue) { 79 | return df.indexOf(i) 80 | } 81 | } 82 | return nil 83 | } 84 | 85 | func (df DataFrame) indexOf(idx int) map[string]elementValue { 86 | m1 := make(map[string]elementValue) 87 | for _, se := range df.columns { 88 | if idx <= len(se.values) { 89 | m1[se.Name] = se.values[idx] 90 | } 91 | } 92 | return m1 93 | } 94 | 95 | func (df DataFrame) column(name string) (Series, error) { 96 | for _, se := range df.columns { 97 | if strings.EqualFold(se.Name, name) { 98 | return se, nil 99 | } 100 | } 101 | return Series{}, errors.New("column(name string) error.") 102 | } 103 | 104 | //like pandas.read_csv(fileFullPath, index_col=0,parse_dates=[0]) 105 | //csvFilePath string, index_col int, parse_dates []int 106 | func Read_csv(paserFormat CsvPaserFormatter) (DataFrame, error) { 107 | 108 | fileContent, _ := ioutil.ReadFile(paserFormat.CsvFilePath) 109 | r := csv.NewReader(strings.NewReader(string(fileContent))) 110 | 111 | var records [][]string 112 | for { 113 | record, err := r.Read() 114 | if err == io.EOF { 115 | break 116 | } 117 | if err != nil { 118 | return EMPTY, err 119 | } 120 | 121 | records = append(records, record) 122 | } 123 | 124 | return PaserCSV(records, paserFormat) 125 | } 126 | 127 | func PaserCSV(records [][]string, paserFormat CsvPaserFormatter) (DataFrame, error) { 128 | 129 | if len(records) == 0 { 130 | return DataFrame{}, errors.New("Empty records") 131 | } 132 | //paserFormat.skiprows 133 | if paserFormat.Skiprows <= 0 { 134 | paserFormat.Skiprows = 0 135 | } 136 | if paserFormat.Skipfooter <= 0 { 137 | paserFormat.Skipfooter = 0 138 | } 139 | 140 | records = TransposeRecords(records) 141 | 142 | var columnNames = make([]string, len(records)) 143 | 144 | seriesArr := make([]Series, len(records)) 145 | 146 | //fmt.Printf("len(records) =%d\n", len(records)) 147 | for i := 0; i < len(records); i++ { 148 | //use the first line as column names 149 | columnNames[i] = records[i][0] 150 | //set Series name 151 | seriesArr[i].Name = records[i][0] 152 | 153 | var stringArr = make([]string, len(records[i])-paserFormat.Skipfooter -paserFormat.Skiprows) 154 | stringArrIndex := 0 155 | 156 | for j := paserFormat.Skiprows; j < len(records[i])-paserFormat.Skipfooter; j++ { 157 | //all use stringElement 158 | stringArr[stringArrIndex] = records[i][j] 159 | stringArrIndex += 1 160 | 161 | } 162 | isIntType := true 163 | isFloatType := true 164 | isBoolType := true 165 | isStringType := true 166 | stringElementArr := Values(Strings(stringArr)) 167 | var floatElementArr = make([]floatElement, len(stringElementArr)) 168 | var intElementArr = make([]intElement, len(stringElementArr)) 169 | var boolElementArr = make([]boolElement, len(stringElementArr)) 170 | for i := 0; i < len(stringElementArr); i++ { 171 | intElementArr[i] = stringElementArr[i].(stringElement).ToInt() 172 | if intElementArr[i].i == nil { 173 | isIntType = false 174 | } 175 | floatElementArr[i] = stringElementArr[i].(stringElement).ToFloat() 176 | if floatElementArr[i].f == nil { 177 | isFloatType = false 178 | } 179 | boolElementArr[i] = stringElementArr[i].(stringElement).ToBool() 180 | if boolElementArr[i].b == nil { 181 | isBoolType = false 182 | } 183 | } 184 | 185 | if isFloatType { 186 | var valuesArr []elementValue = make([]elementValue, len(floatElementArr)) 187 | for i := 0; i < len(floatElementArr); i++ { 188 | valuesArr[i] = floatElementArr[i] 189 | } 190 | seriesArr[i].t = Float_type 191 | seriesArr[i].setValues(&valuesArr) 192 | } 193 | if isIntType { 194 | var valuesArr []elementValue = make([]elementValue, len(intElementArr)) 195 | for i := 0; i < len(intElementArr); i++ { 196 | valuesArr[i] = intElementArr[i] 197 | } 198 | seriesArr[i].t = Int_type 199 | seriesArr[i].setValues(&valuesArr) 200 | } 201 | if isBoolType { 202 | var valuesArr []elementValue = make([]elementValue, len(boolElementArr)) 203 | for i := 0; i < len(boolElementArr); i++ { 204 | valuesArr[i] = boolElementArr[i] 205 | } 206 | seriesArr[i].t = Bool_type 207 | seriesArr[i].setValues(&valuesArr) 208 | } 209 | if (!isFloatType) && (!isIntType) && (!isBoolType) && isStringType { 210 | seriesArr[i].t = String_type 211 | seriesArr[i].setValues(&stringElementArr) 212 | } 213 | 214 | } 215 | //make special column to timeElement 216 | anyElementArr := Values(seriesArr[paserFormat.Parse_dates]) 217 | var timeElementArr = make([]timeElement, len(anyElementArr)) 218 | for i := 0; i < len(anyElementArr); i++ { 219 | timeElementArr[i] = anyElementArr[i].(stringElement).ToTime() 220 | } 221 | 222 | var valuesArr []elementValue = make([]elementValue, len(timeElementArr)) 223 | for i := 0; i < len(timeElementArr); i++ { 224 | valuesArr[i] = timeElementArr[i] 225 | } 226 | seriesArr[paserFormat.Parse_dates].t = Time_type 227 | seriesArr[paserFormat.Parse_dates].setValues(&valuesArr) 228 | 229 | //set index of all series 230 | indexValue := Values(seriesArr[paserFormat.Index_col]) 231 | for i := 0; i < len(seriesArr); i++ { 232 | seriesArr[i].setIndex(&indexValue) 233 | } 234 | 235 | resultDataFrame := DataFrame{} 236 | resultDataFrame.columns = seriesArr 237 | resultDataFrame.ColumnNames = columnNames 238 | 239 | //set index of dataframe 240 | resultDataFrame.Index = indexValue 241 | resultDataFrame.IndexType = seriesArr[paserFormat.Index_col].t 242 | 243 | resultDataFrame.ncols = len(seriesArr) 244 | resultDataFrame.nrows = len(resultDataFrame.Index) 245 | //fmt.Printf("%s \t", resultDataFrame) 246 | 247 | return resultDataFrame, nil 248 | } 249 | 250 | func (df DataFrame) String() string { 251 | var buf bytes.Buffer 252 | buf.WriteString("Name:\t") 253 | buf.WriteString(df.Name) 254 | buf.WriteString("\n") 255 | buf.WriteString("row * column : \t") 256 | buf.WriteString(strconv.Itoa(df.nrows)) 257 | buf.WriteString(" * ") 258 | buf.WriteString(strconv.Itoa(df.ncols)) 259 | buf.WriteString("\n") 260 | 261 | for _, v := range df.ColumnNames { 262 | buf.WriteString(v) 263 | buf.WriteString("\t") 264 | } 265 | buf.WriteString("\n") 266 | var seriesColumns []Series = df.columns 267 | for i := 0; i < df.nrows; i++ { 268 | for _, se := range seriesColumns { 269 | strEle, _ := ToString(se.values[i]) 270 | buf.WriteString(AddLeftPadding(*strEle.s, se.RuneCount+2)) //hard code 2 271 | } 272 | buf.WriteString("\n") 273 | } 274 | 275 | return buf.String() 276 | } 277 | 278 | func (df DataFrame) head() string { 279 | return df.headOf(20) 280 | } 281 | 282 | func (df DataFrame) headOf(num int) string { 283 | var buf bytes.Buffer 284 | buf.WriteString("Name:\t") 285 | buf.WriteString(df.Name) 286 | buf.WriteString("\n") 287 | buf.WriteString("row * column : \t") 288 | buf.WriteString(strconv.Itoa(df.nrows)) 289 | buf.WriteString(" * ") 290 | buf.WriteString(strconv.Itoa(df.ncols)) 291 | buf.WriteString("\n") 292 | 293 | for _, v := range df.ColumnNames { 294 | buf.WriteString(v) 295 | buf.WriteString("\t") 296 | } 297 | buf.WriteString("\n") 298 | var seriesColumns []Series = df.columns 299 | for i := 0; i < df.nrows && i < num; i++ { 300 | for _, se := range seriesColumns { 301 | strEle, _ := ToString(se.values[i]) 302 | buf.WriteString(AddLeftPadding(*strEle.s, se.RuneCount+2)) //hard code 2 303 | } 304 | buf.WriteString("\n") 305 | } 306 | 307 | return buf.String() 308 | } 309 | 310 | func (df DataFrame) tail() string { 311 | return df.tailOf(20) 312 | } 313 | 314 | func (df DataFrame) tailOf(num int) string { 315 | var buf bytes.Buffer 316 | buf.WriteString("Name:\t") 317 | buf.WriteString(df.Name) 318 | buf.WriteString("\n") 319 | buf.WriteString("row * column : \t") 320 | buf.WriteString(strconv.Itoa(df.nrows)) 321 | buf.WriteString(" * ") 322 | buf.WriteString(strconv.Itoa(df.ncols)) 323 | buf.WriteString("\n") 324 | 325 | for _, v := range df.ColumnNames { 326 | buf.WriteString(v) 327 | buf.WriteString("\t") 328 | } 329 | buf.WriteString("\n") 330 | var seriesColumns []Series = df.columns 331 | for i := (df.nrows - num); i < df.nrows; i++ { 332 | for _, se := range seriesColumns { 333 | strEle, _ := ToString(se.values[i]) 334 | buf.WriteString(AddLeftPadding(*strEle.s, se.RuneCount+2)) //hard code 2 335 | } 336 | buf.WriteString("\n") 337 | } 338 | 339 | return buf.String() 340 | } 341 | -------------------------------------------------------------------------------- /dataframe/element.go: -------------------------------------------------------------------------------- 1 | package dataframe 2 | 3 | //this file comes from : github.com\kniren\gota 4 | //a little change 5 | 6 | import ( 7 | "errors" 8 | "fmt" 9 | "reflect" 10 | "strconv" 11 | "strings" 12 | "time" 13 | ) 14 | 15 | type stringElement struct { 16 | s *string 17 | } 18 | 19 | type intElement struct { 20 | i *int 21 | } 22 | 23 | type floatElement struct { 24 | f *float64 25 | } 26 | 27 | type timeElement struct { 28 | t *time.Time 29 | } 30 | 31 | type boolElement struct { 32 | b *bool 33 | } 34 | 35 | type elementInterface interface { 36 | Eq(elementInterface) bool 37 | Less(elementInterface) bool 38 | LessEq(elementInterface) bool 39 | Greater(elementInterface) bool 40 | GreaterEq(elementInterface) bool 41 | ToString() stringElement 42 | ToInt() intElement 43 | ToFloat() floatElement 44 | ToBool() boolElement 45 | ToTime() timeElement 46 | IsNA() bool 47 | Value() elementValue 48 | } 49 | 50 | type elementValue interface{} 51 | 52 | //use go lang standard mode, this is hard code: src/pkg/time/format.go 53 | const format_timeElement_style_default = "2006-01-02" 54 | 55 | //const format_timeElement_style_default = "2006-01-02 15:04:05" 56 | 57 | func createTimeElement(datetimeFormat string, s *string) (timeElement, error) { 58 | if len(datetimeFormat) == 0 { 59 | datetimeFormat = format_timeElement_style_default 60 | } 61 | if t, err := time.Parse(datetimeFormat, *s); err == nil { 62 | return timeElement{&t}, nil 63 | } else { 64 | fmt.Printf("createTimeElement error: %s", err) 65 | panic("createTimeElement error: ") 66 | return timeElement{nil}, errors.New("Parse by datetimeFormat error.") 67 | } 68 | } 69 | 70 | //print the type 71 | func checkit(v interface{}) { 72 | ret, ok := v.(int) 73 | fmt.Printf("check the type: %s, %b\n", ret, ok) 74 | var t = reflect.TypeOf(v) 75 | fmt.Printf("check the reflect type: %v\n", t) 76 | } 77 | 78 | func Eq(e elementValue, in elementValue) bool { 79 | if in == nil { 80 | return false 81 | } 82 | meType := reflect.TypeOf(e) 83 | inType := reflect.TypeOf(in) 84 | if !strings.EqualFold(meType.Name(), inType.Name()) { 85 | return false 86 | } 87 | switch e.(type) { 88 | case intElement: 89 | var ele intElement = e.(intElement) 90 | var inEle intElement = in.(intElement) 91 | return ele.Eq(inEle) 92 | case floatElement: 93 | var ele floatElement = e.(floatElement) 94 | var inEle floatElement = in.(floatElement) 95 | return ele.Eq(inEle) 96 | case stringElement: 97 | var ele stringElement = e.(stringElement) 98 | var inEle stringElement = in.(stringElement) 99 | return ele.Eq(inEle) 100 | case boolElement: 101 | var ele boolElement = e.(boolElement) 102 | var inEle boolElement = in.(boolElement) 103 | return ele.Eq(inEle) 104 | case timeElement: 105 | var ele timeElement = e.(timeElement) 106 | var inEle timeElement = in.(timeElement) 107 | return ele.Eq(inEle) 108 | default: 109 | return false 110 | } 111 | 112 | } 113 | 114 | func ToString(e elementValue) (stringElement, error) { 115 | if e == nil { 116 | return stringElement{nil}, errors.New("elementValue is nil") 117 | } 118 | //fmt.Printf("check the type of elementValue: %s\n",e) 119 | //checkit(e) 120 | switch e.(type) { 121 | case intElement: 122 | var ele intElement = e.(intElement) 123 | return ele.ToString(), nil 124 | case floatElement: 125 | var ele floatElement = e.(floatElement) 126 | return ele.ToString(), nil 127 | case stringElement: 128 | var ele stringElement = e.(stringElement) 129 | return ele.ToString(), nil 130 | case boolElement: 131 | var ele boolElement = e.(boolElement) 132 | return ele.ToString(), nil 133 | case timeElement: 134 | var ele timeElement = e.(timeElement) 135 | return ele.ToString(), nil 136 | default: 137 | var empty string = "" 138 | return stringElement{&empty}, nil 139 | } 140 | } 141 | func ToInt(e elementValue) (intElement, error) { 142 | if e == nil { 143 | var empty int = 0 144 | return intElement{&empty}, errors.New("elementValue is nil") 145 | } 146 | //fmt.Printf("check the type of elementValue: %s\n",e) 147 | //checkit(e) 148 | switch e.(type) { 149 | case intElement: 150 | var ele intElement = e.(intElement) 151 | return ele.ToInt(), nil 152 | case floatElement: 153 | var ele floatElement = e.(floatElement) 154 | return ele.ToInt(), nil 155 | case stringElement: 156 | var ele stringElement = e.(stringElement) 157 | return ele.ToInt(), nil 158 | case boolElement: 159 | var ele boolElement = e.(boolElement) 160 | return ele.ToInt(), nil 161 | case timeElement: 162 | var ele timeElement = e.(timeElement) 163 | return ele.ToInt(), nil 164 | default: 165 | var empty int = 0 166 | return intElement{&empty}, nil 167 | } 168 | } 169 | func ToFloat(e elementValue) (floatElement, error) { 170 | if e == nil { 171 | empty := 0.0 172 | return floatElement{&empty}, errors.New("elementValue is nil") 173 | } 174 | //fmt.Printf("check the type of elementValue: %s\n",e) 175 | //checkit(e) 176 | switch e.(type) { 177 | case intElement: 178 | var ele intElement = e.(intElement) 179 | return ele.ToFloat(), nil 180 | case floatElement: 181 | var ele floatElement = e.(floatElement) 182 | return ele.ToFloat(), nil 183 | case stringElement: 184 | var ele stringElement = e.(stringElement) 185 | return ele.ToFloat(), nil 186 | case boolElement: 187 | var ele boolElement = e.(boolElement) 188 | return ele.ToFloat(), nil 189 | case timeElement: 190 | var ele timeElement = e.(timeElement) 191 | return ele.ToFloat(), nil 192 | default: 193 | empty := 0.0 194 | return floatElement{&empty}, nil 195 | } 196 | } 197 | func ToBool(e elementValue) (boolElement, error) { 198 | if e == nil { 199 | var empty bool = false 200 | return boolElement{&empty}, errors.New("elementValue is nil") 201 | } 202 | //fmt.Printf("check the type of elementValue: %s\n",e) 203 | //checkit(e) 204 | switch e.(type) { 205 | case intElement: 206 | var ele intElement = e.(intElement) 207 | return ele.ToBool(), nil 208 | case floatElement: 209 | var ele floatElement = e.(floatElement) 210 | return ele.ToBool(), nil 211 | case stringElement: 212 | var ele stringElement = e.(stringElement) 213 | return ele.ToBool(), nil 214 | case boolElement: 215 | var ele boolElement = e.(boolElement) 216 | return ele.ToBool(), nil 217 | case timeElement: 218 | var ele timeElement = e.(timeElement) 219 | return ele.ToBool(), nil 220 | default: 221 | var empty bool = false 222 | return boolElement{&empty}, nil 223 | } 224 | } 225 | 226 | func ToTime(e elementValue) (timeElement, error) { 227 | if e == nil { 228 | var empty = time.Now() 229 | return timeElement{&empty}, errors.New("elementValue is nil") 230 | } 231 | //fmt.Printf("check the type of elementValue: %s\n",e) 232 | //checkit(e) 233 | switch e.(type) { 234 | case intElement: 235 | var ele intElement = e.(intElement) 236 | return ele.ToTime(), nil 237 | case floatElement: 238 | var ele floatElement = e.(floatElement) 239 | return ele.ToTime(), nil 240 | case stringElement: 241 | var ele stringElement = e.(stringElement) 242 | return ele.ToTime(), nil 243 | case boolElement: 244 | var ele boolElement = e.(boolElement) 245 | return ele.ToTime(), nil 246 | case timeElement: 247 | var ele timeElement = e.(timeElement) 248 | return ele.ToTime(), nil 249 | default: 250 | var empty = time.Now() 251 | return timeElement{&empty}, nil 252 | } 253 | } 254 | 255 | func (e stringElement) Len() int { 256 | if e.IsNA() { 257 | return 0 258 | } 259 | return len(*e.s) 260 | } 261 | 262 | func (e stringElement) Value() elementValue { 263 | if e.IsNA() { 264 | return nil 265 | } 266 | return *e.s 267 | } 268 | func (e intElement) Value() elementValue { 269 | if e.IsNA() { 270 | return nil 271 | } 272 | return *e.i 273 | } 274 | func (e floatElement) Value() elementValue { 275 | if e.IsNA() { 276 | return nil 277 | } 278 | return *e.f 279 | } 280 | func (e boolElement) Value() elementValue { 281 | if e.IsNA() { 282 | return nil 283 | } 284 | return *e.b 285 | } 286 | func (t timeElement) Value() elementValue { 287 | if t.IsNA() { 288 | return nil 289 | } 290 | return *t.t 291 | } 292 | 293 | func (s stringElement) ToString() stringElement { 294 | return s.Copy() 295 | } 296 | func (i intElement) ToString() stringElement { 297 | if i.IsNA() { 298 | return stringElement{nil} 299 | } 300 | s := i.String() 301 | return stringElement{&s} 302 | } 303 | func (f floatElement) ToString() stringElement { 304 | if f.IsNA() { 305 | return stringElement{nil} 306 | } 307 | s := f.String() 308 | return stringElement{&s} 309 | } 310 | func (t timeElement) ToString() stringElement { 311 | if t.IsNA() { 312 | return stringElement{nil} 313 | } 314 | s := t.String() 315 | return stringElement{&s} 316 | } 317 | func (b boolElement) ToString() stringElement { 318 | if b.IsNA() { 319 | return stringElement{nil} 320 | } 321 | s := b.String() 322 | return stringElement{&s} 323 | } 324 | 325 | func (s stringElement) ToInt() intElement { 326 | if s.s == nil { 327 | return intElement{nil} 328 | } 329 | i, err := strconv.Atoi(*s.s) 330 | if err != nil { 331 | return intElement{nil} 332 | } 333 | if s.IsNA() { 334 | return intElement{nil} 335 | } 336 | return intElement{&i} 337 | } 338 | func (i intElement) ToInt() intElement { 339 | return i.Copy() 340 | } 341 | func (f floatElement) ToInt() intElement { 342 | if f.f != nil { 343 | i := int(*f.f) 344 | return intElement{&i} 345 | } 346 | return intElement{nil} 347 | } 348 | func (b boolElement) ToInt() intElement { 349 | if b.b == nil { 350 | return intElement{nil} 351 | } 352 | var i int 353 | if *b.b { 354 | i = 1 355 | } else { 356 | i = 0 357 | } 358 | return intElement{&i} 359 | } 360 | func (t timeElement) ToInt() intElement { 361 | if t.t != nil { 362 | timeStr := t.t.Format("20060102150405") 363 | i, err := strconv.Atoi(timeStr) 364 | if err != nil { 365 | return intElement{nil} 366 | } 367 | return intElement{&i} 368 | } 369 | return intElement{nil} 370 | } 371 | 372 | func (s stringElement) ToTime() timeElement { 373 | if s.s == nil { 374 | return timeElement{nil} 375 | } 376 | if tme, err := createTimeElement(format_timeElement_style_default, s.s); err == nil { 377 | return tme 378 | } 379 | return timeElement{nil} 380 | } 381 | 382 | func (t timeElement) ToTime() timeElement { 383 | return t.Copy() 384 | } 385 | func (i intElement) ToTime() timeElement { 386 | timeStr := strconv.Itoa(*i.i) 387 | if tme, err := createTimeElement(format_timeElement_style_default, &timeStr); err == nil { 388 | return tme 389 | } 390 | return timeElement{nil} 391 | } 392 | 393 | func (f floatElement) ToTime() timeElement { 394 | timeStr := strconv.FormatFloat(float64(*f.f), 'f', 6, 64) 395 | if tme, err := createTimeElement(format_timeElement_style_default, &timeStr); err == nil { 396 | return tme 397 | } 398 | return timeElement{nil} 399 | } 400 | func (b boolElement) ToTime() timeElement { 401 | return timeElement{nil} 402 | } 403 | 404 | func (s stringElement) ToFloat() floatElement { 405 | if s.s == nil { 406 | return floatElement{nil} 407 | } 408 | f, err := strconv.ParseFloat(*s.s, 64) 409 | if err != nil { 410 | return floatElement{nil} 411 | } 412 | return floatElement{&f} 413 | } 414 | func (i floatElement) ToFloat() floatElement { 415 | return i.Copy() 416 | } 417 | func (i intElement) ToFloat() floatElement { 418 | if i.i != nil { 419 | f := float64(*i.i) 420 | return floatElement{&f} 421 | } 422 | return floatElement{nil} 423 | } 424 | func (b boolElement) ToFloat() floatElement { 425 | if b.b == nil { 426 | return floatElement{nil} 427 | } 428 | var f float64 429 | if *b.b { 430 | f = 1.0 431 | } else { 432 | f = 0.0 433 | } 434 | return floatElement{&f} 435 | } 436 | func (t timeElement) ToFloat() floatElement { 437 | if t.t != nil { 438 | timeStr := t.t.Format("20060102150405") 439 | i, err := strconv.Atoi(timeStr) 440 | if err != nil { 441 | return floatElement{nil} 442 | } 443 | f := float64(i) 444 | return floatElement{&f} 445 | } 446 | return floatElement{nil} 447 | } 448 | 449 | func (s stringElement) ToBool() boolElement { 450 | if s.s == nil { 451 | return boolElement{nil} 452 | } 453 | var b bool 454 | if *s.s == "false" { 455 | b = false 456 | return boolElement{&b} 457 | } 458 | if *s.s == "true" { 459 | b = true 460 | return boolElement{&b} 461 | } 462 | return boolElement{nil} 463 | } 464 | func (i intElement) ToBool() boolElement { 465 | if i.i == nil { 466 | return boolElement{nil} 467 | } 468 | var b bool 469 | if *i.i == 1 { 470 | b = true 471 | } 472 | if *i.i == 0 { 473 | b = false 474 | } 475 | return boolElement{&b} 476 | } 477 | func (f floatElement) ToBool() boolElement { 478 | if f.f == nil { 479 | return boolElement{nil} 480 | } 481 | var b bool 482 | if *f.f == 1.0 { 483 | b = true 484 | } else if *f.f == 0.0 { 485 | b = false 486 | } else { 487 | return boolElement{nil} 488 | } 489 | return boolElement{&b} 490 | } 491 | func (i boolElement) ToBool() boolElement { 492 | return i.Copy() 493 | } 494 | func (t timeElement) ToBool() boolElement { 495 | var b bool 496 | return boolElement{&b} 497 | } 498 | 499 | func (s stringElement) LessEq(elem elementInterface) bool { 500 | if elem == nil { 501 | return false 502 | } 503 | e := elem.ToString() 504 | if s.IsNA() || e.IsNA() { 505 | return false 506 | } 507 | return *s.s <= *e.s 508 | } 509 | func (s intElement) LessEq(elem elementInterface) bool { 510 | if elem == nil { 511 | return false 512 | } 513 | e := elem.ToInt() 514 | if s.IsNA() || e.IsNA() { 515 | return false 516 | } 517 | return *s.i <= *e.i 518 | } 519 | func (s floatElement) LessEq(elem elementInterface) bool { 520 | if elem == nil { 521 | return false 522 | } 523 | e := elem.ToFloat() 524 | if s.IsNA() || e.IsNA() { 525 | return false 526 | } 527 | return *s.f <= *e.f 528 | } 529 | func (s boolElement) LessEq(elem elementInterface) bool { 530 | if elem == nil { 531 | return false 532 | } 533 | e := elem.ToBool() 534 | if s.IsNA() || e.IsNA() { 535 | return false 536 | } 537 | if *s.b && !*e.b { 538 | return false 539 | } 540 | return true 541 | } 542 | func (t timeElement) LessEq(elem elementInterface) bool { 543 | if elem == nil { 544 | return false 545 | } 546 | e := elem.ToTime() 547 | if t.IsNA() || e.IsNA() { 548 | return false 549 | } 550 | return (*t.t).Before(*e.t) 551 | } 552 | 553 | func (s stringElement) Less(elem elementInterface) bool { 554 | if elem == nil { 555 | return false 556 | } 557 | e := elem.ToString() 558 | if s.IsNA() || e.IsNA() { 559 | return false 560 | } 561 | return *s.s < *e.s 562 | } 563 | func (s intElement) Less(elem elementInterface) bool { 564 | if elem == nil { 565 | return false 566 | } 567 | e := elem.ToInt() 568 | if s.IsNA() || e.IsNA() { 569 | return false 570 | } 571 | return *s.i < *e.i 572 | } 573 | func (s floatElement) Less(elem elementInterface) bool { 574 | if elem == nil { 575 | return false 576 | } 577 | e := elem.ToFloat() 578 | if s.IsNA() || e.IsNA() { 579 | return false 580 | } 581 | return *s.f < *e.f 582 | } 583 | func (s boolElement) Less(elem elementInterface) bool { 584 | if elem == nil { 585 | return false 586 | } 587 | e := elem.ToBool() 588 | if s.IsNA() || e.IsNA() { 589 | return false 590 | } 591 | if *s.b { 592 | return false 593 | } 594 | if *e.b { 595 | return true 596 | } 597 | return false 598 | } 599 | func (t timeElement) Less(elem elementInterface) bool { 600 | if elem == nil { 601 | return false 602 | } 603 | e := elem.ToTime() 604 | if t.IsNA() || e.IsNA() { 605 | return false 606 | } 607 | return (*t.t).Before(*e.t) 608 | } 609 | 610 | func (s stringElement) GreaterEq(elem elementInterface) bool { 611 | if elem == nil { 612 | return false 613 | } 614 | e := elem.ToString() 615 | if s.IsNA() || e.IsNA() { 616 | return false 617 | } 618 | return *s.s >= *e.s 619 | } 620 | func (s intElement) GreaterEq(elem elementInterface) bool { 621 | if elem == nil { 622 | return false 623 | } 624 | e := elem.ToInt() 625 | if s.IsNA() || e.IsNA() { 626 | return false 627 | } 628 | return *s.i >= *e.i 629 | } 630 | func (s floatElement) GreaterEq(elem elementInterface) bool { 631 | if elem == nil { 632 | return false 633 | } 634 | e := elem.ToFloat() 635 | if s.IsNA() || e.IsNA() { 636 | return false 637 | } 638 | return *s.f >= *e.f 639 | } 640 | func (s boolElement) GreaterEq(elem elementInterface) bool { 641 | if elem == nil { 642 | return false 643 | } 644 | e := elem.ToBool() 645 | if s.IsNA() || e.IsNA() { 646 | return false 647 | } 648 | if *s.b { 649 | return true 650 | } 651 | if *e.b { 652 | return false 653 | } 654 | return true 655 | } 656 | func (t timeElement) GreaterEq(elem elementInterface) bool { 657 | if elem == nil { 658 | return false 659 | } 660 | e := elem.ToTime() 661 | if t.IsNA() || e.IsNA() { 662 | return false 663 | } 664 | return (*t.t).After(*e.t) 665 | } 666 | 667 | func (s stringElement) Greater(elem elementInterface) bool { 668 | if elem == nil { 669 | return false 670 | } 671 | e := elem.ToString() 672 | if s.IsNA() || e.IsNA() { 673 | return false 674 | } 675 | return *s.s > *e.s 676 | } 677 | func (s intElement) Greater(elem elementInterface) bool { 678 | if elem == nil { 679 | return false 680 | } 681 | e := elem.ToInt() 682 | if s.IsNA() || e.IsNA() { 683 | return false 684 | } 685 | return *s.i > *e.i 686 | } 687 | func (s floatElement) Greater(elem elementInterface) bool { 688 | if elem == nil { 689 | return false 690 | } 691 | e := elem.ToFloat() 692 | if s.IsNA() || e.IsNA() { 693 | return false 694 | } 695 | return *s.f > *e.f 696 | } 697 | func (t timeElement) Greater(elem elementInterface) bool { 698 | if elem == nil { 699 | return false 700 | } 701 | e := elem.ToTime() 702 | if t.IsNA() || e.IsNA() { 703 | return false 704 | } 705 | return (*t.t).After(*e.t) 706 | } 707 | 708 | func (s boolElement) Greater(elem elementInterface) bool { 709 | if elem == nil { 710 | return false 711 | } 712 | e := elem.ToBool() 713 | if s.IsNA() || e.IsNA() { 714 | return false 715 | } 716 | if *s.b && !*e.b { 717 | return true 718 | } 719 | return false 720 | } 721 | 722 | func (s stringElement) Eq(elem elementInterface) bool { 723 | if elem == nil { 724 | return false 725 | } 726 | e := elem.ToString() 727 | if s.IsNA() || e.IsNA() { 728 | return false 729 | } 730 | return *s.s == *e.s 731 | } 732 | 733 | func (s intElement) Eq(elem elementInterface) bool { 734 | if elem == nil { 735 | return false 736 | } 737 | e := elem.ToInt() 738 | if s.IsNA() || e.IsNA() { 739 | return false 740 | } 741 | return *s.i == *e.i 742 | } 743 | 744 | func (s floatElement) Eq(elem elementInterface) bool { 745 | if elem == nil { 746 | return false 747 | } 748 | e := elem.ToFloat() 749 | if s.IsNA() || e.IsNA() { 750 | return false 751 | } 752 | return *s.f == *e.f 753 | } 754 | func (t timeElement) Eq(elem elementInterface) bool { 755 | if elem == nil { 756 | return false 757 | } 758 | e := elem.ToTime() 759 | if t.IsNA() || e.IsNA() { 760 | return false 761 | } 762 | //use this will get : invalid indirect of t.t.Unix() (type int64) 763 | //time1 := *t.t.Unix() 764 | time1 := (*t.t).Unix() 765 | time2 := (*e.t).Unix() 766 | 767 | return time1 == time2 768 | } 769 | 770 | func (s boolElement) Eq(elem elementInterface) bool { 771 | if elem == nil { 772 | return false 773 | } 774 | e := elem.ToBool() 775 | if s.IsNA() || e.IsNA() { 776 | return false 777 | } 778 | return *s.b == *e.b 779 | } 780 | 781 | func (s stringElement) String() string { 782 | if s.s == nil { 783 | return "NA" 784 | } 785 | return *s.s 786 | } 787 | func (i intElement) String() string { 788 | if i.i == nil { 789 | return "NA" 790 | } 791 | return fmt.Sprintf("%d", *i.i) 792 | } 793 | func (f floatElement) String() string { 794 | if f.f == nil { 795 | return "NA" 796 | } 797 | return fmt.Sprintf("%.2f", *f.f) 798 | } 799 | func (t timeElement) String() string { 800 | if t.t == nil { 801 | return "NA" 802 | } 803 | return fmt.Sprintf("%v", *t.t) 804 | } 805 | func (b boolElement) String() string { 806 | if b.b == nil { 807 | return "NA" 808 | } 809 | if *b.b { 810 | return "true" 811 | } 812 | return "false" 813 | } 814 | 815 | func (s stringElement) Copy() stringElement { 816 | if s.s == nil { 817 | return stringElement{nil} 818 | } 819 | copy := *s.s 820 | return stringElement{©} 821 | } 822 | 823 | func (i intElement) Copy() intElement { 824 | if i.i == nil { 825 | return intElement{nil} 826 | } 827 | copy := *i.i 828 | return intElement{©} 829 | } 830 | 831 | func (t timeElement) Copy() timeElement { 832 | if t.t == nil { 833 | return timeElement{nil} 834 | } 835 | copy := *t.t 836 | return timeElement{©} 837 | } 838 | 839 | func (f floatElement) Copy() floatElement { 840 | if f.f == nil { 841 | return floatElement{nil} 842 | } 843 | copy := *f.f 844 | return floatElement{©} 845 | } 846 | 847 | func (b boolElement) Copy() boolElement { 848 | if b.b == nil { 849 | return boolElement{nil} 850 | } 851 | copy := *b.b 852 | return boolElement{©} 853 | } 854 | 855 | // IsNA returns true if the element is empty and viceversa 856 | func (s stringElement) IsNA() bool { 857 | if s.s == nil { 858 | return true 859 | } 860 | return false 861 | } 862 | 863 | // IsNA returns true if the element is empty and viceversa 864 | func (i intElement) IsNA() bool { 865 | if i.i == nil { 866 | return true 867 | } 868 | return false 869 | } 870 | 871 | // IsNA returns true if the element is empty and viceversa 872 | func (f floatElement) IsNA() bool { 873 | if f.f == nil { 874 | return true 875 | } 876 | return false 877 | } 878 | 879 | func (t timeElement) IsNA() bool { 880 | if t.t == nil { 881 | return true 882 | } 883 | return false 884 | } 885 | 886 | // IsNA returns true if the element is empty and viceversa 887 | func (b boolElement) IsNA() bool { 888 | if b.b == nil { 889 | return true 890 | } 891 | return false 892 | } 893 | --------------------------------------------------------------------------------