-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-23291][SQL][R] R's substr should not reduce starting position by 1 when calling Scala API #20464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
One more thing to notice is that the two parameters (starting and ending positions) of R's substr API is also unaligned with Scala's substr which takes starting position and substring length. |
|
Also @shivaram |
|
One thing to keep in mind is what the user's perception of the API is. If R users are going to use 1-based indexing then this might not be the right fix ? http://stat.ethz.ch/R-manual/R-devel/library/base/html/substr.html is the base R function FWIW |
|
@shivaram This fix is to make it correctly 1-based. Previously SparkR substr API substracts starting position by 1, so it becomes zero-based. This fix matches R's substr in above link as I test: > substr("Michael", 4, 6)
[1] "hae"Before this fix, SparkR's substr returns "cha". |
|
Thanks for clarifying @viirya. Is the PR description accurate ? I read it as |
|
Test build #86908 has finished for PR 20464 at commit
|
|
@shivaram Thanks for pointing out it. I made change to the description. Hopefully it is clearer now. Basically I just want to clarify why R's substr tests are correct previously. |
|
I was just manually double checking both substr in R and this. It seems correct; however, I think we should add a note in the doc and release note ... One followup question is though, would it be difficult to match the behaviour with substr in R when the index is 0 or minus? If i understood #20464 (comment) correctly, it sounds better to match it to substr's behaviour in R. Took a quick look/test and seems we can just set If this followup question is something we are not sure yet, I think we might be okay as is. |
|
Just in case, I am testing with: df <- createDataFrame(list(list(a="abcdef")))
collect(select(df, substr(df$a, 4, 5)))
substr("abcdef", 4, 5)just in case it helps to check and reproduce. |
If we both consider the indices at starting and ending, setting them to 1 seems not enough. E.g., > substr("abcdef", -2, -3)
[1] ""
> substr("abcdef", 1, 1)
[1] "a"For the cases when only ending is zero/negative, no matter what starting is, the result is empty string. For the cases when only starting is zero/negative, we can set it to 1. For the cases they are both zero/negative, the result is empty string. We can address this in another PR. |
| setMethod("substr", signature(x = "Column"), | ||
| function(x, start, stop) { | ||
| jc <- callJMethod(x@jc, "substr", as.integer(start - 1), as.integer(stop - start + 1)) | ||
| jc <- callJMethod(x@jc, "substr", as.integer(start), as.integer(stop - start + 1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit concern with changing this. As you can see it's been like this from the very beginning...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This API behavior should be considered as wrong and performs inconsistently. Because for starting position 1, we get substring from 1st element, but for position 2, we still get the substring from 1. So we will get the following inconsistent results:
> collect(select(df, substr(df$a, 1, 5)))
substring(a, 0, 5)
1 abcde
> collect(select(df, substr(df$a, 2, 5)))
substring(a, 1, 4)
1 abcdFor such change, we might need to add a note in the doc as @HyukjinKwon suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question:
- is there a way to make the behavior the same before this change for any caller calling substr with common index like 0
- why consider other changes as a follow up and not here?
[SPARK-23291][SQL][R] R's substr should not reduce starting position by 1 when calling Scala API #20464 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- why consider other changes as a follow up and not here? #20464 (comment)
Just because I think it is another issue regarding 0/negative indices. I can deal it here if you strongly feel it is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a way to make the behavior the same before this change for any caller calling substr with common index like 0
Should we keep the behavior when calling substr with 0 as start index?
> df <- createDataFrame(list(list(a="abcdef")))
> collect(select(df, substr(df$a, 0, 5)))
substring(a, -1, 6)
1 f
> substr("abcdef", 0, 5)
[1] "abcde"I think the previous behavior is pretty unreasonable..
|
Test build #86924 has finished for PR 20464 at commit
|
docs/sparkr.md
Outdated
|
|
||
| ## Upgrading to Spark 2.4.0 | ||
|
|
||
| - The first parameter of `substr` method was wrongly subtracted by one, previously. This can lead to inconsistent substring results and also does not match with the behaviour with `substr` in R. It has been corrected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of The first parameter of -> The ``start`` parameter of...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
| setMethod("substr", signature(x = "Column"), | ||
| function(x, start, stop) { | ||
| jc <- callJMethod(x@jc, "substr", as.integer(start - 1), as.integer(stop - start + 1)) | ||
| jc <- callJMethod(x@jc, "substr", as.integer(start), as.integer(stop - start + 1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question:
- is there a way to make the behavior the same before this change for any caller calling substr with common index like 0
- why consider other changes as a follow up and not here?
[SPARK-23291][SQL][R] R's substr should not reduce starting position by 1 when calling Scala API #20464 (comment)
|
Test build #86985 has finished for PR 20464 at commit
|
HyukjinKwon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I admit it's correct .. so LGTM but let me leave it to @felixcheung and @shivaram ..
|
I think @felixcheung has the most context here, so I'd suggest we wait for his comments. |
|
ping @felixcheung |
|
Sorry, I'm a bit occupied with testing 2.3 RC, will get back to this after. |
|
@felixcheung Thanks! |
|
Because 2.3 is released, ping @felixcheung again |
| setMethod("substr", signature(x = "Column"), | ||
| function(x, start, stop) { | ||
| jc <- callJMethod(x@jc, "substr", as.integer(start - 1), as.integer(stop - start + 1)) | ||
| jc <- callJMethod(x@jc, "substr", as.integer(start), as.integer(stop - start + 1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should do two things:
- add to the func doc that the
startparam should be 0-base and to add to the example with the result
collect(select(df, substr(df$a, 0, 5))) # this should give you...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you mean 1-base.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to the func doc.
docs/sparkr.md
Outdated
|
|
||
| ## Upgrading to Spark 2.4.0 | ||
|
|
||
| - The `start` parameter of `substr` method was wrongly subtracted by one, previously. This can lead to inconsistent substring results and also does not match with the behaviour with `substr` in R. It has been corrected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- in the migration guide we should give a concrete example with non-0 start index, eg.
substr(df$a, 1, 6)should be changed tosubstr(df$a, 0, 5)
|
Test build #87993 has finished for PR 20464 at commit
|
|
appveyor tests failed, could you close and reopen this PR to trigger it. strange, I haven't seen anything like this on appveyor a long time. |
felixcheung
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG, pending tests.
one small comment for clarity. thanks!
docs/sparkr.md
Outdated
|
|
||
| ## Upgrading to Spark 2.4.0 | ||
|
|
||
| - The `start` parameter of `substr` method was wrongly subtracted by one, previously. In other words, the index specified by `start` parameter was considered as 0-base. This can lead to inconsistent substring results and also does not match with the behaviour with `substr` in R. It has been fixed so the `start` parameter of `substr` method is now 1-base, e.g., `substr(df$a, 2, 5)` should be changed to `substr(df$a, 1, 4)`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you add
method is now 1-base, e.g., therefore to get the same result as substr(df$a, 2, 5), it should be changed to substr(df$a, 1, 4)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Added.
|
Test build #88039 has finished for PR 20464 at commit
|
|
merged to master, thanks! |
…by 1 when calling Scala API ## What changes were proposed in this pull request? Seems R's substr API treats Scala substr API as zero based and so subtracts the given starting position by 1. Because Scala's substr API also accepts zero-based starting position (treated as the first element), so the current R's substr test results are correct as they all use 1 as starting positions. ## How was this patch tested? Modified tests. Author: Liang-Chi Hsieh <viirya@gmail.com> Closes apache#20464 from viirya/SPARK-23291.
What changes were proposed in this pull request?
Seems R's substr API treats Scala substr API as zero based and so subtracts the given starting position by 1.
Because Scala's substr API also accepts zero-based starting position (treated as the first element), so the current R's substr test results are correct as they all use 1 as starting positions.
How was this patch tested?
Modified tests.