Uh oh!
There was an error while loading. Please reload this page.
[SPARK-23291][SQL][R] R's substr should not reduce starting position by 1 when calling Scala API - #20464
[SPARK-23291][SQL][R] R's substr should not reduce starting position by 1 when calling Scala API#20464viirya wants to merge 5 commits into
Conversation
viirya
commented
Feb 1, 2018
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. |
viirya
commented
Feb 1, 2018
srowen
commented
Feb 1, 2018
Also @shivaram |
shivaram
commented
Feb 1, 2018
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 |
viirya
commented
Feb 1, 2018
@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". |
shivaram
commented
Feb 1, 2018
Thanks for clarifying @viirya. Is the PR description accurate ? I read it as |
SparkQA
commented
Feb 1, 2018
Test build #86908 has finished for PR 20464 at commit
|
viirya
commented
Feb 1, 2018
@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. |
HyukjinKwon
commented
Feb 1, 2018
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. |
HyukjinKwon
commented
Feb 1, 2018
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. |
viirya
commented
Feb 1, 2018
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.
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.
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)
1abcde> collect(select(df, substr(df$a, 2, 5)))
substring(a, 1, 4)
1abcdFor such change, we might need to add a note in the doc as @HyukjinKwon suggested.
There was a problem hiding this comment.
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.
- 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.
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)
1f> substr("abcdef", 0, 5)
[1] "abcde"I think the previous behavior is pretty unreasonable..
SparkQA
commented
Feb 1, 2018
Test build #86924 has finished for PR 20464 at commit
|
| ## 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.
instead of The first parameter of -> The ``start`` parameter of...
| 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.
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)
SparkQA
commented
Feb 2, 2018
Test build #86985 has finished for PR 20464 at commit
|
HyukjinKwon
left a comment
There was a problem hiding this comment.
I admit it's correct .. so LGTM but let me leave it to @felixcheung and @shivaram ..
shivaram
commented
Feb 7, 2018
I think @felixcheung has the most context here, so I'd suggest we wait for his comments. |
viirya
commented
Feb 15, 2018
ping @felixcheung |
felixcheung
commented
Feb 16, 2018
Sorry, I'm a bit occupied with testing 2.3 RC, will get back to this after. |
viirya
commented
Feb 16, 2018
@felixcheung Thanks! |
viirya
commented
Mar 2, 2018
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.
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 resultcollect(select(df, substr(df$a, 0, 5))) # this should give you...
| ## 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.
- 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)
SparkQA
commented
Mar 6, 2018
Test build #87993 has finished for PR 20464 at commit
|
felixcheung
commented
Mar 6, 2018
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.
LG, pending tests.
one small comment for clarity. thanks!
| ## 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.
could you addmethod 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)
SparkQA
commented
Mar 7, 2018
Test build #88039 has finished for PR 20464 at commit
|
felixcheung
commented
Mar 7, 2018
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> Closesapache#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.