{"action":"created","comment":{"url":"https://api.github.com/repos/apache/spark/pulls/comments/28487029","id":28487029,"diff_hunk":"@@ -0,0 +1,274 @@\n+/*\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\n+ * contributor license agreements.  See the NOTICE file distributed with\n+ * this work for additional information regarding copyright ownership.\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\n+ * (the \"License\"); you may not use this file except in compliance with\n+ * the License.  You may obtain a copy of the License at\n+ *\n+ *    http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+package org.apache.spark.ml.classification\n+\n+import org.scalatest.FunSuite\n+\n+import org.apache.spark.ml.impl.TreeTests\n+import org.apache.spark.mllib.linalg.Vectors\n+import org.apache.spark.mllib.regression.LabeledPoint\n+import org.apache.spark.mllib.tree.{DecisionTree => OldDecisionTree,\n+  DecisionTreeSuite => OldDecisionTreeSuite}\n+import org.apache.spark.mllib.util.MLlibTestSparkContext\n+import org.apache.spark.rdd.RDD\n+import org.apache.spark.sql.DataFrame\n+\n+\n+class DecisionTreeClassifierSuite extends FunSuite with MLlibTestSparkContext {\n+\n+  import DecisionTreeClassifierSuite.compareAPIs\n+\n+  private var categoricalDataPointsRDD: RDD[LabeledPoint] = _\n+  private var orderedLabeledPointsWithLabel0RDD: RDD[LabeledPoint] = _\n+  private var orderedLabeledPointsWithLabel1RDD: RDD[LabeledPoint] = _\n+  private var categoricalDataPointsForMulticlassRDD: RDD[LabeledPoint] = _\n+  private var continuousDataPointsForMulticlassRDD: RDD[LabeledPoint] = _\n+  private var categoricalDataPointsForMulticlassForOrderedFeaturesRDD: RDD[LabeledPoint] = _\n+\n+  override def beforeAll() {\n+    super.beforeAll()\n+    categoricalDataPointsRDD =\n+      sc.parallelize(OldDecisionTreeSuite.generateCategoricalDataPoints())\n+    orderedLabeledPointsWithLabel0RDD =\n+      sc.parallelize(OldDecisionTreeSuite.generateOrderedLabeledPointsWithLabel0())\n+    orderedLabeledPointsWithLabel1RDD =\n+      sc.parallelize(OldDecisionTreeSuite.generateOrderedLabeledPointsWithLabel1())\n+    categoricalDataPointsForMulticlassRDD =\n+      sc.parallelize(OldDecisionTreeSuite.generateCategoricalDataPointsForMulticlass())\n+    continuousDataPointsForMulticlassRDD =\n+      sc.parallelize(OldDecisionTreeSuite.generateContinuousDataPointsForMulticlass())\n+    categoricalDataPointsForMulticlassForOrderedFeaturesRDD = sc.parallelize(\n+      OldDecisionTreeSuite.generateCategoricalDataPointsForMulticlassForOrderedFeatures())\n+  }\n+\n+  /////////////////////////////////////////////////////////////////////////////\n+  // Tests calling train()\n+  /////////////////////////////////////////////////////////////////////////////\n+\n+  test(\"Binary classification stump with ordered categorical features\") {\n+    val dt = new DecisionTreeClassifier()\n+      .setImpurity(\"gini\")\n+      .setMaxDepth(2)\n+      .setMaxBins(100)\n+    val categoricalFeatures = Map(0 -> 3, 1-> 3)\n+    val numClasses = 2\n+    compareAPIs(categoricalDataPointsRDD, dt, categoricalFeatures, numClasses)\n+  }\n+\n+  test(\"Binary classification stump with fixed labels 0,1 for Entropy,Gini\") {\n+    val dt = new DecisionTreeClassifier()\n+      .setMaxDepth(3)\n+      .setMaxBins(100)\n+    val numClasses = 2\n+    Array(orderedLabeledPointsWithLabel0RDD, orderedLabeledPointsWithLabel1RDD).foreach { rdd =>\n+      DecisionTreeClassifier.supportedImpurities.foreach { impurity =>\n+        dt.setImpurity(impurity)\n+        compareAPIs(rdd, dt, categoricalFeatures = Map.empty[Int, Int], numClasses)\n+      }\n+    }\n+  }\n+\n+  test(\"Multiclass classification stump with 3-ary (unordered) categorical features\") {\n+    val rdd = categoricalDataPointsForMulticlassRDD\n+    val dt = new DecisionTreeClassifier()\n+      .setImpurity(\"Gini\")\n+      .setMaxDepth(4)\n+    val numClasses = 3\n+    val categoricalFeatures = Map(0 -> 3, 1 -> 3)\n+    compareAPIs(rdd, dt, categoricalFeatures, numClasses)\n+  }\n+\n+  test(\"Binary classification stump with 1 continuous feature, to check off-by-1 error\") {\n+    val arr = new Array[LabeledPoint](4)\n+    arr(0) = new LabeledPoint(0.0, Vectors.dense(0.0))\n+    arr(1) = new LabeledPoint(1.0, Vectors.dense(1.0))\n+    arr(2) = new LabeledPoint(1.0, Vectors.dense(2.0))\n+    arr(3) = new LabeledPoint(1.0, Vectors.dense(3.0))","path":"mllib/src/test/scala/org/apache/spark/ml/classification/DecisionTreeClassifierSuite.scala","position":101,"original_position":101,"commit_id":"5626c81cc896a04fc109d09ee145487c116ecf6d","original_commit_id":"5626c81cc896a04fc109d09ee145487c116ecf6d","user":{"login":"mengxr","id":829644,"avatar_url":"https://avatars.githubusercontent.com/u/829644?v=3","gravatar_id":"","url":"https://api.github.com/users/mengxr","html_url":"https://github.com/mengxr","followers_url":"https://api.github.com/users/mengxr/followers","following_url":"https://api.github.com/users/mengxr/following{/other_user}","gists_url":"https://api.github.com/users/mengxr/gists{/gist_id}","starred_url":"https://api.github.com/users/mengxr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mengxr/subscriptions","organizations_url":"https://api.github.com/users/mengxr/orgs","repos_url":"https://api.github.com/users/mengxr/repos","events_url":"https://api.github.com/users/mengxr/events{/privacy}","received_events_url":"https://api.github.com/users/mengxr/received_events","type":"User","site_admin":false},"body":"~~~scala\r\nval arr = Array(\r\n  new LabelPoint(...),\r\n  new ...\r\n}\r\n~~~","created_at":"2015-04-16T06:40:07Z","updated_at":"2015-04-16T06:40:07Z","html_url":"https://github.com/apache/spark/pull/5530#discussion_r28487029","pull_request_url":"https://api.github.com/repos/apache/spark/pulls/5530","_links":{"self":{"href":"https://api.github.com/repos/apache/spark/pulls/comments/28487029"},"html":{"href":"https://github.com/apache/spark/pull/5530#discussion_r28487029"},"pull_request":{"href":"https://api.github.com/repos/apache/spark/pulls/5530"}}},"pull_request":{"url":"https://api.github.com/repos/apache/spark/pulls/5530","id":33372731,"html_url":"https://github.com/apache/spark/pull/5530","diff_url":"https://github.com/apache/spark/pull/5530.diff","patch_url":"https://github.com/apache/spark/pull/5530.patch","issue_url":"https://api.github.com/repos/apache/spark/issues/5530","number":5530,"state":"open","locked":false,"title":"[SPARK-6113] [ml] Stabilize DecisionTree API","user":{"login":"jkbradley","id":5084283,"avatar_url":"https://avatars.githubusercontent.com/u/5084283?v=3","gravatar_id":"","url":"https://api.github.com/users/jkbradley","html_url":"https://github.com/jkbradley","followers_url":"https://api.github.com/users/jkbradley/followers","following_url":"https://api.github.com/users/jkbradley/following{/other_user}","gists_url":"https://api.github.com/users/jkbradley/gists{/gist_id}","starred_url":"https://api.github.com/users/jkbradley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jkbradley/subscriptions","organizations_url":"https://api.github.com/users/jkbradley/orgs","repos_url":"https://api.github.com/users/jkbradley/repos","events_url":"https://api.github.com/users/jkbradley/events{/privacy}","received_events_url":"https://api.github.com/users/jkbradley/received_events","type":"User","site_admin":false},"body":"This is a PR for cleaning up and finalizing the DecisionTree API.  PRs for ensembles will follow once this is merged.\r\n\r\n### Goal\r\n\r\nHere is the description copied from the JIRA (for both trees and ensembles):\r\n\r\n> **Issue**: The APIs for DecisionTree and ensembles (RandomForests and GradientBoostedTrees) have been experimental for a long time. The API has become very convoluted because trees and ensembles have many, many variants, some of which we have added incrementally without a long-term design.\r\n> **Proposal**: This JIRA is for discussing changes required to finalize the APIs. After we discuss, I will make a PR to update the APIs and make them non-Experimental. This will require making many breaking changes; see the design doc for details.\r\n> **[Design doc](https://docs.google.com/document/d/1rJ_DZinyDG3PkYkAKSsQlY0QgCeefn4hUv7GsPkzBP4)** : This outlines current issues and the proposed API.\r\n\r\nOverall code layout:\r\n* The old API in mllib.tree.* will remain the same.\r\n* The new API will reside in ml.classification.* and ml.regression.*\r\n\r\n### Summary of changes\r\n\r\nOld API\r\n* Exactly the same, except I made 1 method in Loss private (but that is not a breaking change since that method was introduced after the Spark 1.3 release).\r\n\r\nNew APIs\r\n* Under Pipeline API\r\n* The new API preserves functionality, except:\r\n  * New API does NOT store prob (probability of label in classification).  I want to have it store the full vector of probabilities but feel that should be in a later PR.\r\n* Use abstractions for parameters, estimators, and models to avoid code duplication\r\n* Limit parameters to relevant algorithms\r\n* For enum-like types, only expose Strings\r\n  * We can make these pluggable later on by adding new parameters.  That is a far-future item.\r\n\r\nTest suites\r\n* I organized DecisionTreeSuite, but I made absolutely no changes to the tests themselves.\r\n* The test suites for the new API only test (a) similarity with the results of the old API and (b) elements of the new API.\r\n  * After code is moved to this new API, we should move the tests from the old suites which test the internals.\r\n\r\n### Details\r\n\r\n#### Changed names\r\n\r\nParameters\r\n* useNodeIdCache -> cacheNodeIds\r\n\r\n#### Other changes\r\n\r\n* Split: Changed categories to set instead of list\r\n\r\n#### Non-decision tree changes\r\n* AttributeGroup\r\n  * Added parentheses to toMetadata, toStructField methods (These were removed in a previous PR, but I ran into 1 issue with the Scala compiler not being able to disambiguate between a toMetadata method with no parentheses and a toMetadata method which takes 1 argument.)\r\n* Attributes\r\n  * Renamed: toMetadata -> toMetadataImpl\r\n  * Added toMetadata methods which return ML metadata (keyed with “ML_ATTR”)\r\n  * NominalAttribute: Added getNumValues method which examines both numValues and values.\r\n* Params.inheritValues: Checks whether the parent param really belongs to the child (to allow Estimator-Model pairs with different sets of parameters)\r\n\r\n### Questions for reviewers\r\n\r\n* Is \"DecisionTreeClassificationModel\" too long a name?\r\n* Is this OK in the docs?\r\n```\r\nclass DecisionTreeRegressor extends TreeRegressor[DecisionTreeRegressionModel] with DecisionTreeParams[DecisionTreeRegressor] with TreeRegressorParams[DecisionTreeRegressor]\r\n```\r\n\r\n### Future\r\n\r\nWe should open up the abstractions at some point.  E.g., it would be useful to be able to set tree-related parameters in 1 place and then pass those to multiple tree-based algorithms.\r\n\r\nFollow-up JIRAs will be (in this order):\r\n* Tree ensembles\r\n* Deprecate old tree code\r\n* Move DecisionTree implementation code to new API.\r\n* Move tests from the old suites which test the internals.\r\n* Update programming guide\r\n* Python API\r\n* Change RandomForest* to always use bootstrapping, even when numTrees = 1\r\n* Provide the probability of the predicted label for classification.  After we move code to the new API and update it to maintain probabilities for all labels, then we can add the probabilities to the new API.\r\n\r\nCC: @mengxr  @manishamde  @codedeft  @chouqin  @MechCoder","created_at":"2015-04-15T16:31:25Z","updated_at":"2015-04-16T06:40:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c856f5640310fb3e1b1cccf4de79a0f8e6c6df56","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apache/spark/pulls/5530/commits","review_comments_url":"https://api.github.com/repos/apache/spark/pulls/5530/comments","review_comment_url":"https://api.github.com/repos/apache/spark/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/spark/issues/5530/comments","statuses_url":"https://api.github.com/repos/apache/spark/statuses/5626c81cc896a04fc109d09ee145487c116ecf6d","head":{"label":"jkbradley:dt-api-dt","ref":"dt-api-dt","sha":"5626c81cc896a04fc109d09ee145487c116ecf6d","user":{"login":"jkbradley","id":5084283,"avatar_url":"https://avatars.githubusercontent.com/u/5084283?v=3","gravatar_id":"","url":"https://api.github.com/users/jkbradley","html_url":"https://github.com/jkbradley","followers_url":"https://api.github.com/users/jkbradley/followers","following_url":"https://api.github.com/users/jkbradley/following{/other_user}","gists_url":"https://api.github.com/users/jkbradley/gists{/gist_id}","starred_url":"https://api.github.com/users/jkbradley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jkbradley/subscriptions","organizations_url":"https://api.github.com/users/jkbradley/orgs","repos_url":"https://api.github.com/users/jkbradley/repos","events_url":"https://api.github.com/users/jkbradley/events{/privacy}","received_events_url":"https://api.github.com/users/jkbradley/received_events","type":"User","site_admin":false},"repo":{"id":19877817,"name":"spark","full_name":"jkbradley/spark","owner":{"login":"jkbradley","id":5084283,"avatar_url":"https://avatars.githubusercontent.com/u/5084283?v=3","gravatar_id":"","url":"https://api.github.com/users/jkbradley","html_url":"https://github.com/jkbradley","followers_url":"https://api.github.com/users/jkbradley/followers","following_url":"https://api.github.com/users/jkbradley/following{/other_user}","gists_url":"https://api.github.com/users/jkbradley/gists{/gist_id}","starred_url":"https://api.github.com/users/jkbradley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jkbradley/subscriptions","organizations_url":"https://api.github.com/users/jkbradley/orgs","repos_url":"https://api.github.com/users/jkbradley/repos","events_url":"https://api.github.com/users/jkbradley/events{/privacy}","received_events_url":"https://api.github.com/users/jkbradley/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jkbradley/spark","description":"Mirror of Apache Spark","fork":true,"url":"https://api.github.com/repos/jkbradley/spark","forks_url":"https://api.github.com/repos/jkbradley/spark/forks","keys_url":"https://api.github.com/repos/jkbradley/spark/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jkbradley/spark/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jkbradley/spark/teams","hooks_url":"https://api.github.com/repos/jkbradley/spark/hooks","issue_events_url":"https://api.github.com/repos/jkbradley/spark/issues/events{/number}","events_url":"https://api.github.com/repos/jkbradley/spark/events","assignees_url":"https://api.github.com/repos/jkbradley/spark/assignees{/user}","branches_url":"https://api.github.com/repos/jkbradley/spark/branches{/branch}","tags_url":"https://api.github.com/repos/jkbradley/spark/tags","blobs_url":"https://api.github.com/repos/jkbradley/spark/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jkbradley/spark/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jkbradley/spark/git/refs{/sha}","trees_url":"https://api.github.com/repos/jkbradley/spark/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jkbradley/spark/statuses/{sha}","languages_url":"https://api.github.com/repos/jkbradley/spark/languages","stargazers_url":"https://api.github.com/repos/jkbradley/spark/stargazers","contributors_url":"https://api.github.com/repos/jkbradley/spark/contributors","subscribers_url":"https://api.github.com/repos/jkbradley/spark/subscribers","subscription_url":"https://api.github.com/repos/jkbradley/spark/subscription","commits_url":"https://api.github.com/repos/jkbradley/spark/commits{/sha}","git_commits_url":"https://api.github.com/repos/jkbradley/spark/git/commits{/sha}","comments_url":"https://api.github.com/repos/jkbradley/spark/comments{/number}","issue_comment_url":"https://api.github.com/repos/jkbradley/spark/issues/comments{/number}","contents_url":"https://api.github.com/repos/jkbradley/spark/contents/{+path}","compare_url":"https://api.github.com/repos/jkbradley/spark/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jkbradley/spark/merges","archive_url":"https://api.github.com/repos/jkbradley/spark/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jkbradley/spark/downloads","issues_url":"https://api.github.com/repos/jkbradley/spark/issues{/number}","pulls_url":"https://api.github.com/repos/jkbradley/spark/pulls{/number}","milestones_url":"https://api.github.com/repos/jkbradley/spark/milestones{/number}","notifications_url":"https://api.github.com/repos/jkbradley/spark/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jkbradley/spark/labels{/name}","releases_url":"https://api.github.com/repos/jkbradley/spark/releases{/id}","created_at":"2014-05-17T03:51:41Z","updated_at":"2015-04-13T22:36:19Z","pushed_at":"2015-04-15T20:38:32Z","git_url":"git://github.com/jkbradley/spark.git","ssh_url":"git@github.com:jkbradley/spark.git","clone_url":"https://github.com/jkbradley/spark.git","svn_url":"https://github.com/jkbradley/spark","homepage":null,"size":103169,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":0,"forks":2,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apache:master","ref":"master","sha":"6c5ed8a6d552abd967d27cdb94b68d46ccb57221","user":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":17165658,"name":"spark","full_name":"apache/spark","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/spark","description":"Mirror of Apache Spark","fork":false,"url":"https://api.github.com/repos/apache/spark","forks_url":"https://api.github.com/repos/apache/spark/forks","keys_url":"https://api.github.com/repos/apache/spark/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/spark/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/spark/teams","hooks_url":"https://api.github.com/repos/apache/spark/hooks","issue_events_url":"https://api.github.com/repos/apache/spark/issues/events{/number}","events_url":"https://api.github.com/repos/apache/spark/events","assignees_url":"https://api.github.com/repos/apache/spark/assignees{/user}","branches_url":"https://api.github.com/repos/apache/spark/branches{/branch}","tags_url":"https://api.github.com/repos/apache/spark/tags","blobs_url":"https://api.github.com/repos/apache/spark/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/spark/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/spark/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/spark/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/spark/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/spark/languages","stargazers_url":"https://api.github.com/repos/apache/spark/stargazers","contributors_url":"https://api.github.com/repos/apache/spark/contributors","subscribers_url":"https://api.github.com/repos/apache/spark/subscribers","subscription_url":"https://api.github.com/repos/apache/spark/subscription","commits_url":"https://api.github.com/repos/apache/spark/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/spark/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/spark/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/spark/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/spark/contents/{+path}","compare_url":"https://api.github.com/repos/apache/spark/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/spark/merges","archive_url":"https://api.github.com/repos/apache/spark/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/spark/downloads","issues_url":"https://api.github.com/repos/apache/spark/issues{/number}","pulls_url":"https://api.github.com/repos/apache/spark/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/spark/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/spark/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/spark/labels{/name}","releases_url":"https://api.github.com/repos/apache/spark/releases{/id}","created_at":"2014-02-25T08:00:08Z","updated_at":"2015-04-16T06:08:06Z","pushed_at":"2015-04-16T06:15:30Z","git_url":"git://github.com/apache/spark.git","ssh_url":"git@github.com:apache/spark.git","clone_url":"https://github.com/apache/spark.git","svn_url":"https://github.com/apache/spark","homepage":null,"size":1502668,"stargazers_count":3631,"watchers_count":3631,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":3128,"mirror_url":"git://git.apache.org/spark.git","open_issues_count":292,"forks":3128,"open_issues":292,"watchers":3631,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/spark/pulls/5530"},"html":{"href":"https://github.com/apache/spark/pull/5530"},"issue":{"href":"https://api.github.com/repos/apache/spark/issues/5530"},"comments":{"href":"https://api.github.com/repos/apache/spark/issues/5530/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/spark/pulls/5530/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/spark/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/spark/pulls/5530/commits"},"statuses":{"href":"https://api.github.com/repos/apache/spark/statuses/5626c81cc896a04fc109d09ee145487c116ecf6d"}}}}