diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..d5a2e6dc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,286 @@ +# Contributing Guide + +### Contributing to danfojs + +**Table of contents:** + +* **TL:DR** +* Where to start? +* Working with the code + * Version control, Git, and GitHub + * Getting started with Git + * Forking + * Creating a development environment +* Documentation Guidelines +* Writing tests + * Using mocha + * Running the test suite +* Contributing your changes to danfojs + * Committing your code + * Pushing your changes + * Review your code and finally, make the pull request +* Danfojs internal (Brief) + +## TL:DR + +All contributions, bug reports, bug fixes, documentation improvements, enhancements, and ideas are welcome. + +For contributors familiar with open-source, below is a quick guide to setting up danfojs locally. + +``` +git clone https://github.com/javascriptdata/danfojs.git +cd danfojs +git checkout -b +``` + +There are three main folders in the `src` folder, **danfojs-base**, **danfojs-browser,** and **danfojs-node**. + +The **danfojs-base** folder holds all shared classes, modules, and functions used by both danfojs-browser and danfojs-node. So features or bug fixes that work the same way in both versions will generally be done in the **danfojs-base** folder. + +## Where to start? + +For first-time contributors, you can find pending issues on the GitHub “issues” page. There are a number of issues listed and "good first issue" where you could start out. Once you’ve found an interesting issue, and have an improvement in mind, next thing is to set up your development environment. + +## Working with the code + +If you have an issue you want to fix, an enhancement to add, or documentation to improve, you need to learn how to work with GitHub and the Danfojs code base. + +### **Version control, Git, and GitHub** + +Danfojs code is hosted on GitHub. To contribute you will need to sign up for a free GitHub account. We use Git for version control to allow many people to work together on this project. + +Some great resources for learning Git: + +* Official [GitHub pages](http://help.github.com). + +### **Getting started with Git** + +Find [Instructions](http://help.github.com/set-up-git-redirect) for installing git, setting up your SSH key, and configuring git. These steps need to be completed before you can work seamlessly between your local repository and GitHub. + +## **Forking the Danfojs repo** + +You will need your own fork to work on the code. Go to the danfojs [project page](https://github.com/opensource9ja/danfojs) and hit the Fork button. + +Next, you will clone your fork to your local machine: + +``` +git clone https://github.com/javascriptdata/danfojs.git +cd danfojs +``` + +This creates the directory danfojs and connects your repository to the upstream (main project) repository. + +Some Javascript features are supported both in the browser and node environment, and it is recommended to add features in the **danfojs-base** folder. + +For features that work differently or only in a specific environment, you can add them in the corresponding danfojs-node or danfojs-browser folder. + + + +## **Creating a development environment** + +To test out code changes, you’ll need to build danfojs, which requires a Nodejs environment. + +```python +git clone https://github.com/javascriptdata/danfojs.git +cd danfojs +yarn install ## automatically installs all required packages +yarn test ##Runs test in both node and browser folder +``` + +> Now you can start adding features or fixing bugs! + +## Documentation Guidelines + +Documentation helps clarify what a function or a method is doing. It also gives insight to users of the function or methods on what parameters to pass in and know what the function will return. + +Sample documentation: + +```javascript + /** + * Add two series of the same length + * @param {series1} series1 [Series] + * @param {series2} series2 [Series] + * @returns Series + */ +function add_series(series1, series2){ + + ................... + + return new Series() +} +``` + +And for functions that contain more than two arguments, a keyword argument can be used. Parsing of keyword argument is also applicable to most of the methods in a class + +```javascript +/** + * Join two or more dataframe together along an axis + * @param {kwargs} kwargs --> { + * df_list: [Array of DataFrame], + * axis : int {0 or 1}, + * by_column : String {name of a column}, + * } + * @returns DataFrame + */ +function join_df(kwargs){ + ........ + + return DataFrame +} +``` + +## **Writing tests** + +We strongly encourage contributors to write tests for their code. Like many packages, Danfojs uses mocha. + +All tests should go into the tests subdirectory and placed in the corresponding module. The tests folder contains some current examples of tests, and we suggest looking to these for inspiration. + +Below is the general Framework to write a test for each module. + +{% tabs %} +{% tab title="JavaScript" %} +```javascript +import { assert } from "chai" +import { DataFrame } from '../../src/core/frame' + +describe("Name of the class|module", function(){ + + it("name of the methods| expected result",function(){ + + //write your test code here + //use assert.{proprty} to test your code + }) + +}); +``` +{% endtab %} +{% endtabs %} + +For a class with lots of methods. + +```python +import { assert } from "chai" +import { DataFrame } from '../../src/core/frame' + +describe("Name of the class|module", function(){ + + describe("method name 1", function(){ + + it("expected result",function(){ + + //write your test code here + //use assert.{proprty} to test your code + }) + }) + + describe("method name 2", function(){ + + it("expected result",function(){ + + //write your test code here + //use assert.{proprty} to test your code + }) + }) + ....... +}); +``` + +**Example**: Let write a test, to test if the values in a dataframe are off a certain length. Assuming the method to obtain length is values\_len() + +```javascript +import { assert } from "chai" +import { DataFrame } from '../../src/core/frame' + +describe("DataFrame", function(){ + + describe("value_len", function(){ + + it("check dataframe length",function(){ + + let data = [[1,2],[4,5]] + let columns = ["A","B"] + let df = new DataFrame(data,{columns: columns}) + + let expected_result = 2 + + assert.deepEqual(sf.value_len(), expected_result)) + + + }) + }) + +}); +``` + +### **Running the test case** + +To run the test for the module you created, + +**1)** Open the package.json + +**2)** change the name of the test script to the file name you want to test. + +```python +"scripts": { + "test": "....... danfojs/tests/sub_directory_name/filename", +``` + +**3)** run the test, in the danfojs directory terminal + +```python +yarn test +``` + +Learn more about mocha [here](https://mochajs.org) + +## Contributing your changes to danfojs + +### **Committing your code** + +Once you’ve made changes, you can see them by typing: + +``` +git status +``` + +Next, you can track your changes using + +``` +git add . +``` + +Next, you commit changes using: + +``` +git commit -m "Enter any commit message here" +``` + +### **Pushing your changes** + +When you want your changes to appear publicly on your GitHub page, you can push to your forked repo with: + +``` +git push +``` + +### Review your code and finally, make a pull request + +If everything looks good, you are ready to make a pull request. A pull request is how code from a local repository becomes available to the GitHub community and can be reviewed and eventually merged into the master version. To submit a pull request: + +1. Navigate to your repository on GitHub +2. Click on the Pull Request button +3. Write a description of your changes in the Preview Discussion tab +4. Click Send Pull Request. + +This request then goes to the repository maintainers, and they will review the code and everything looks good, merge it with the master. + +**Hooray! You're now a contributor to danfojs. Now go bask in the euphoria!** + +## **Danfojs Internals** + +In other to contribute to the code base of danfojs, there are some functions and properties provided to make implementation easy. + +The folder **danfojs-base** contains the bulk of Danfojs modules, and these are simply extended or exported by the **danfojs-browser** and **danfojs-node** folders. The base class for Frames and Series is the NdFrame class which is found in the `danfojs-base/core/generic` file. + + + diff --git a/README.md b/README.md index 2dcbbafe..a3cbeada 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ yarn add danfojs For use directly in HTML files, you can add the latest script tag from [JsDelivr](https://www.jsdelivr.com/package/npm/danfojs) to your HTML file: ```html - + ``` See all available versions [here](https://www.jsdelivr.com/package/npm/danfojs) @@ -85,7 +85,7 @@ See all available versions [here](https://www.jsdelivr.com/package/npm/danfojs) - + Document diff --git a/src/danfojs-base/aggregators/groupby.ts b/src/danfojs-base/aggregators/groupby.ts index d12a8d43..2c1224c6 100644 --- a/src/danfojs-base/aggregators/groupby.ts +++ b/src/danfojs-base/aggregators/groupby.ts @@ -441,6 +441,14 @@ export default class Groupby { return this.operations("sum") } + /** + * Obtain the standard deviation of columns for each group + * @returns DataFrame + */ + std(): DataFrame{ + return this.operations("std") + } + /** * Obtain the variance of columns for each group * @returns DataFrame diff --git a/src/danfojs-base/core/frame.ts b/src/danfojs-base/core/frame.ts index 7cdd004f..b9e575c4 100644 --- a/src/danfojs-base/core/frame.ts +++ b/src/danfojs-base/core/frame.ts @@ -2754,14 +2754,18 @@ export default class DataFrame extends NDframe implements DataFrameInterface { * */ rename( - mapper: any, + mapper: { + [index: string | number]: string | number + }, options?: { axis?: 0 | 1 inplace?: boolean } ): DataFrame - rename( - mapper: any, + rename( + mapper: { + [index: string | number]: string | number + }, options?: { axis?: 0 | 1 inplace?: boolean @@ -2777,8 +2781,9 @@ export default class DataFrame extends NDframe implements DataFrameInterface { const colsAdded: string[] = []; const newColumns = this.columns.map(col => { if (mapper[col] !== undefined) { - colsAdded.push(mapper[col]); - return mapper[col] + const newCol = `${mapper[col]}`; + colsAdded.push(newCol); + return newCol; } else { return col } diff --git a/src/danfojs-base/index.ts b/src/danfojs-base/index.ts index 8e3d62e5..e1ff1e24 100644 --- a/src/danfojs-base/index.ts +++ b/src/danfojs-base/index.ts @@ -29,7 +29,7 @@ import merge from "./transformers/merge" import dateRange from "./core/daterange" import tensorflow from "./shared/tensorflowlib" -const __version = "1.0.0" +const __version = "1.0.1"; export { NDframe, diff --git a/src/danfojs-base/io/browser/io.csv.ts b/src/danfojs-base/io/browser/io.csv.ts index e05d42da..d22eecd3 100644 --- a/src/danfojs-base/io/browser/io.csv.ts +++ b/src/danfojs-base/io/browser/io.csv.ts @@ -51,6 +51,7 @@ const $readCSV = async (file: any, options?: CsvInputOptionsBrowser): Promise { Papa.parse(file, { header: true, + dynamicTyping: true, ...options, download: true, complete: results => { @@ -83,6 +84,7 @@ const $streamCSV = async (file: string, callback: (df: DataFrame) => void, optio let count = -1 Papa.parse(file, { ...options, + dynamicTyping: true, header: true, download: true, step: results => { diff --git a/src/danfojs-base/io/node/io.csv.ts b/src/danfojs-base/io/node/io.csv.ts index 1de24619..80f51409 100644 --- a/src/danfojs-base/io/node/io.csv.ts +++ b/src/danfojs-base/io/node/io.csv.ts @@ -54,6 +54,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis return new Promise(resolve => { const optionsWithDefaults = { header: true, + dynamicTyping: true, ...options, } @@ -76,6 +77,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis const fileStream = fs.createReadStream(filePath) Papa.parse(fileStream, { header: true, + dynamicTyping: true, ...options, complete: results => { const df = new DataFrame(results.data, frameConfig); @@ -107,6 +109,7 @@ const $streamCSV = async (filePath: string, callback: (df: DataFrame) => void, o if (filePath.startsWith("http") || filePath.startsWith("https")) { const optionsWithDefaults = { header: true, + dynamicTyping: true, ...options, } return new Promise(resolve => { @@ -132,6 +135,7 @@ const $streamCSV = async (filePath: string, callback: (df: DataFrame) => void, o let count = -1 Papa.parse(fileStream, { header: true, + dynamicTyping: true, ...options, step: results => { const df = new DataFrame([results.data], { ...frameConfig, index: [count++] }); @@ -223,7 +227,7 @@ const $openCsvInputStream = (filePath: string, options: CsvInputOptionsNode) => if (filePath.startsWith("http") || filePath.startsWith("https")) { const dataStream = request.get(filePath); - const parseStream: any = Papa.parse(Papa.NODE_STREAM_INPUT, { header, ...options }); + const parseStream: any = Papa.parse(Papa.NODE_STREAM_INPUT, { header, dynamicTyping: true, ...options }); dataStream.pipe(parseStream); let count = -1 @@ -255,7 +259,7 @@ const $openCsvInputStream = (filePath: string, options: CsvInputOptionsNode) => const fileStream = fs.createReadStream(filePath) let count = -1 Papa.parse(fileStream, { - ...{ header, ...options }, + ...{ header, dynamicTyping: true, ...options }, step: results => { if (isFirstChunk) { if (header === true) { diff --git a/src/danfojs-base/yarn.lock b/src/danfojs-base/yarn.lock index af8dc9bf..3922f9a3 100644 --- a/src/danfojs-base/yarn.lock +++ b/src/danfojs-base/yarn.lock @@ -3433,9 +3433,9 @@ flatted@^3.1.0: integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== follow-redirects@^1.0.0: - version "1.14.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.6.tgz#8cfb281bbc035b3c067d6cd975b0f6ade6e855cd" - integrity sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A== + version "1.14.7" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" + integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== for-in@^1.0.2: version "1.0.2" diff --git a/src/danfojs-browser/README.md b/src/danfojs-browser/README.md index 5b4edfd2..98fbf1da 100644 --- a/src/danfojs-browser/README.md +++ b/src/danfojs-browser/README.md @@ -71,7 +71,7 @@ yarn add danfojs For use directly in HTML files, you can add the latest script tag from [JsDelivr](https://www.jsdelivr.com/package/npm/danfojs) to your HTML file: ```html - + ``` See all available versions [here](https://www.jsdelivr.com/package/npm/danfojs) @@ -86,7 +86,7 @@ See all available versions [here](https://www.jsdelivr.com/package/npm/danfojs) - + Document diff --git a/src/danfojs-browser/package.json b/src/danfojs-browser/package.json index da8248cf..3854aa91 100644 --- a/src/danfojs-browser/package.json +++ b/src/danfojs-browser/package.json @@ -1,6 +1,6 @@ { "name": "danfojs", - "version": "1.0.0", + "version": "1.0.1", "description": "JavaScript library providing high performance, intuitive, and easy to use data structures for manipulating and processing structured data.", "main": "dist/danfojs-browser/src/index.js", "types": "dist/danfojs-browser/src/index.d.ts", @@ -25,7 +25,6 @@ "papaparse": "^5.3.1", "plotly.js-dist-min": "^2.8.0", "request": "^2.88.2", - "seedrandom": "^2.4.3", "stream-json": "^1.7.3", "table": "6.7.1", "xlsx": "^0.17.2", diff --git a/src/danfojs-browser/tests/io/csv.reader.test.js b/src/danfojs-browser/tests/io/csv.reader.test.js index d66aecd6..17892295 100644 --- a/src/danfojs-browser/tests/io/csv.reader.test.js +++ b/src/danfojs-browser/tests/io/csv.reader.test.js @@ -58,6 +58,16 @@ describe("readCSV", function () { ]); }); + it("Read remote csv file works and returns correct data type", async function () { + const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/src/danfojs-node/test/samples/titanic.csv"; + let df = await dfd.readCSV(remoteFile, { header: true, preview: 2 }); + const values = [ + [ 0, 3, 'Mr. Owen Harris Braund', 'male', 22, 1, 0, 7.25 ], + [ 1, 1, 'Mrs. John Bradley (Florence Briggs Thayer) Cumings', 'female', 38, 1, 0, 71.2833 ] + ]; + assert.deepEqual(df.values, values); + }); + }); // describe("streamCSV", function () { diff --git a/src/danfojs-browser/yarn.lock b/src/danfojs-browser/yarn.lock index 79804963..bf857024 100644 --- a/src/danfojs-browser/yarn.lock +++ b/src/danfojs-browser/yarn.lock @@ -3338,9 +3338,9 @@ flatted@^3.1.0: integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== follow-redirects@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7" - integrity sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg== + version "1.14.7" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" + integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== for-in@^1.0.2: version "1.0.2" diff --git a/src/danfojs-node/README.md b/src/danfojs-node/README.md index 5b4edfd2..98fbf1da 100644 --- a/src/danfojs-node/README.md +++ b/src/danfojs-node/README.md @@ -71,7 +71,7 @@ yarn add danfojs For use directly in HTML files, you can add the latest script tag from [JsDelivr](https://www.jsdelivr.com/package/npm/danfojs) to your HTML file: ```html - + ``` See all available versions [here](https://www.jsdelivr.com/package/npm/danfojs) @@ -86,7 +86,7 @@ See all available versions [here](https://www.jsdelivr.com/package/npm/danfojs) - + Document diff --git a/src/danfojs-node/package.json b/src/danfojs-node/package.json index aa24f2aa..c9a026a0 100644 --- a/src/danfojs-node/package.json +++ b/src/danfojs-node/package.json @@ -1,6 +1,6 @@ { "name": "danfojs-node", - "version": "1.0.0", + "version": "1.0.1", "description": "JavaScript library providing high performance, intuitive, and easy to use data structures for manipulating and processing structured data.", "main": "dist/danfojs-node/src/index.js", "types": "dist/danfojs-node/src/index.d.ts", @@ -29,7 +29,6 @@ "table": "6.7.1", "xlsx": "^0.17.2", "plotly.js-dist-min": "^2.8.0" - }, "scripts": { "test": "nyc mocha --require ts-node/register test/**/*.test.ts", diff --git a/src/danfojs-node/test/io/csv.reader.test.ts b/src/danfojs-node/test/io/csv.reader.test.ts index 752f7ed2..88fcc416 100644 --- a/src/danfojs-node/test/io/csv.reader.test.ts +++ b/src/danfojs-node/test/io/csv.reader.test.ts @@ -59,7 +59,19 @@ describe("readCSV", function () { 'int32', 'float32' ]); }); - + it("Read local csv with correct types and format works", async function () { + const filePath = path.join(process.cwd(), "test", "samples", "iris.csv"); + let df: any = await readCSV(filePath, { header: true, preview: 5 }); + const values = [ + [5.1, 3.5, 1.4, 0.2, 0.0], + [4.9, 3.0, 1.4, 0.2, 0.0], + [4.7, 3.2, 1.3, 0.2, 0.0], + [4.6, 3.1, 1.5, 0.2, 0.0], + [5.0, 3.6, 1.4, 0.2, 0.0], + ] + console.log(df.values) + assert.deepEqual(df.values, values); + }); // it("Read remote csv file works", async function () { // const remoteFile = "https://raw.githubusercontent.com/opensource9ja/danfojs/dev/danfojs-node/tests/samples/titanic.csv" // let df: any = await readCSV(remoteFile, { header: true, preview: 5 }); diff --git a/src/danfojs-node/test/samples/iris.csv b/src/danfojs-node/test/samples/iris.csv new file mode 100644 index 00000000..95c15f1b --- /dev/null +++ b/src/danfojs-node/test/samples/iris.csv @@ -0,0 +1,151 @@ +sepal length (cm),sepal width (cm),petal length (cm),petal width (cm),target +5.1,3.5,1.4,0.2,0.0 +4.9,3.0,1.4,0.2,0.0 +4.7,3.2,1.3,0.2,0.0 +4.6,3.1,1.5,0.2,0.0 +5.0,3.6,1.4,0.2,0.0 +5.4,3.9,1.7,0.4,0.0 +4.6,3.4,1.4,0.3,0.0 +5.0,3.4,1.5,0.2,0.0 +4.4,2.9,1.4,0.2,0.0 +4.9,3.1,1.5,0.1,0.0 +5.4,3.7,1.5,0.2,0.0 +4.8,3.4,1.6,0.2,0.0 +4.8,3.0,1.4,0.1,0.0 +4.3,3.0,1.1,0.1,0.0 +5.8,4.0,1.2,0.2,0.0 +5.7,4.4,1.5,0.4,0.0 +5.4,3.9,1.3,0.4,0.0 +5.1,3.5,1.4,0.3,0.0 +5.7,3.8,1.7,0.3,0.0 +5.1,3.8,1.5,0.3,0.0 +5.4,3.4,1.7,0.2,0.0 +5.1,3.7,1.5,0.4,0.0 +4.6,3.6,1.0,0.2,0.0 +5.1,3.3,1.7,0.5,0.0 +4.8,3.4,1.9,0.2,0.0 +5.0,3.0,1.6,0.2,0.0 +5.0,3.4,1.6,0.4,0.0 +5.2,3.5,1.5,0.2,0.0 +5.2,3.4,1.4,0.2,0.0 +4.7,3.2,1.6,0.2,0.0 +4.8,3.1,1.6,0.2,0.0 +5.4,3.4,1.5,0.4,0.0 +5.2,4.1,1.5,0.1,0.0 +5.5,4.2,1.4,0.2,0.0 +4.9,3.1,1.5,0.2,0.0 +5.0,3.2,1.2,0.2,0.0 +5.5,3.5,1.3,0.2,0.0 +4.9,3.6,1.4,0.1,0.0 +4.4,3.0,1.3,0.2,0.0 +5.1,3.4,1.5,0.2,0.0 +5.0,3.5,1.3,0.3,0.0 +4.5,2.3,1.3,0.3,0.0 +4.4,3.2,1.3,0.2,0.0 +5.0,3.5,1.6,0.6,0.0 +5.1,3.8,1.9,0.4,0.0 +4.8,3.0,1.4,0.3,0.0 +5.1,3.8,1.6,0.2,0.0 +4.6,3.2,1.4,0.2,0.0 +5.3,3.7,1.5,0.2,0.0 +5.0,3.3,1.4,0.2,0.0 +7.0,3.2,4.7,1.4,1.0 +6.4,3.2,4.5,1.5,1.0 +6.9,3.1,4.9,1.5,1.0 +5.5,2.3,4.0,1.3,1.0 +6.5,2.8,4.6,1.5,1.0 +5.7,2.8,4.5,1.3,1.0 +6.3,3.3,4.7,1.6,1.0 +4.9,2.4,3.3,1.0,1.0 +6.6,2.9,4.6,1.3,1.0 +5.2,2.7,3.9,1.4,1.0 +5.0,2.0,3.5,1.0,1.0 +5.9,3.0,4.2,1.5,1.0 +6.0,2.2,4.0,1.0,1.0 +6.1,2.9,4.7,1.4,1.0 +5.6,2.9,3.6,1.3,1.0 +6.7,3.1,4.4,1.4,1.0 +5.6,3.0,4.5,1.5,1.0 +5.8,2.7,4.1,1.0,1.0 +6.2,2.2,4.5,1.5,1.0 +5.6,2.5,3.9,1.1,1.0 +5.9,3.2,4.8,1.8,1.0 +6.1,2.8,4.0,1.3,1.0 +6.3,2.5,4.9,1.5,1.0 +6.1,2.8,4.7,1.2,1.0 +6.4,2.9,4.3,1.3,1.0 +6.6,3.0,4.4,1.4,1.0 +6.8,2.8,4.8,1.4,1.0 +6.7,3.0,5.0,1.7,1.0 +6.0,2.9,4.5,1.5,1.0 +5.7,2.6,3.5,1.0,1.0 +5.5,2.4,3.8,1.1,1.0 +5.5,2.4,3.7,1.0,1.0 +5.8,2.7,3.9,1.2,1.0 +6.0,2.7,5.1,1.6,1.0 +5.4,3.0,4.5,1.5,1.0 +6.0,3.4,4.5,1.6,1.0 +6.7,3.1,4.7,1.5,1.0 +6.3,2.3,4.4,1.3,1.0 +5.6,3.0,4.1,1.3,1.0 +5.5,2.5,4.0,1.3,1.0 +5.5,2.6,4.4,1.2,1.0 +6.1,3.0,4.6,1.4,1.0 +5.8,2.6,4.0,1.2,1.0 +5.0,2.3,3.3,1.0,1.0 +5.6,2.7,4.2,1.3,1.0 +5.7,3.0,4.2,1.2,1.0 +5.7,2.9,4.2,1.3,1.0 +6.2,2.9,4.3,1.3,1.0 +5.1,2.5,3.0,1.1,1.0 +5.7,2.8,4.1,1.3,1.0 +6.3,3.3,6.0,2.5,2.0 +5.8,2.7,5.1,1.9,2.0 +7.1,3.0,5.9,2.1,2.0 +6.3,2.9,5.6,1.8,2.0 +6.5,3.0,5.8,2.2,2.0 +7.6,3.0,6.6,2.1,2.0 +4.9,2.5,4.5,1.7,2.0 +7.3,2.9,6.3,1.8,2.0 +6.7,2.5,5.8,1.8,2.0 +7.2,3.6,6.1,2.5,2.0 +6.5,3.2,5.1,2.0,2.0 +6.4,2.7,5.3,1.9,2.0 +6.8,3.0,5.5,2.1,2.0 +5.7,2.5,5.0,2.0,2.0 +5.8,2.8,5.1,2.4,2.0 +6.4,3.2,5.3,2.3,2.0 +6.5,3.0,5.5,1.8,2.0 +7.7,3.8,6.7,2.2,2.0 +7.7,2.6,6.9,2.3,2.0 +6.0,2.2,5.0,1.5,2.0 +6.9,3.2,5.7,2.3,2.0 +5.6,2.8,4.9,2.0,2.0 +7.7,2.8,6.7,2.0,2.0 +6.3,2.7,4.9,1.8,2.0 +6.7,3.3,5.7,2.1,2.0 +7.2,3.2,6.0,1.8,2.0 +6.2,2.8,4.8,1.8,2.0 +6.1,3.0,4.9,1.8,2.0 +6.4,2.8,5.6,2.1,2.0 +7.2,3.0,5.8,1.6,2.0 +7.4,2.8,6.1,1.9,2.0 +7.9,3.8,6.4,2.0,2.0 +6.4,2.8,5.6,2.2,2.0 +6.3,2.8,5.1,1.5,2.0 +6.1,2.6,5.6,1.4,2.0 +7.7,3.0,6.1,2.3,2.0 +6.3,3.4,5.6,2.4,2.0 +6.4,3.1,5.5,1.8,2.0 +6.0,3.0,4.8,1.8,2.0 +6.9,3.1,5.4,2.1,2.0 +6.7,3.1,5.6,2.4,2.0 +6.9,3.1,5.1,2.3,2.0 +5.8,2.7,5.1,1.9,2.0 +6.8,3.2,5.9,2.3,2.0 +6.7,3.3,5.7,2.5,2.0 +6.7,3.0,5.2,2.3,2.0 +6.3,2.5,5.0,1.9,2.0 +6.5,3.0,5.2,2.0,2.0 +6.2,3.4,5.4,2.3,2.0 +5.9,3.0,5.1,1.8,2.0