Reputation: 23
At some part of my code I have the following observe object. It works fine until I add an if statment inside it. The statment executes right away when the script runs and does not wait for the action associated to observe to be triggered. What do I have to do in order to "hold the horses" of this if inside observe?
observe({
print("UPDATING COORDS")
print(input$map_marker_dragend)
id <- input$map_marker_dragend$id
lat_nova <- input$map_marker_dragend$lat
lon_nova <- input$map_marker_dragend$lng
print(lat_nova)
print(lon_nova)
print(WP$df$latitude)
df2 <- ifelse(is.null(df2), WP$df, df2) # this is the line causing problem
df2 <- if (is.null(df2)) return(WP$df) else return(df2) # this is a second try to make it work
df2$latitude[which(WP$df$id == id)] <- lat_nova
df2$longitude[which(WP$df$id == id)] <- lon_nova
print(df2$latitude)
print(df2, width = Inf)
# declaring to later use
WP$df2 = df2
})
Basically what I want is that shiny checks if df2 exists... if not than df2 should be WP$df... if yes than df2 = df2 and proceed with calculations.
Thanks!
Upvotes: 0
Views: 87
Reputation: 160687
ifelse
is vectorized, and the length of the return value is dependent on the length of the conditional (first argument). I'm inferring that your df2
and WP$df2
are data.frame
s, which means that while the length if is.null(df2)
is length 1, the "length" of WP$df
is not, it is actually the same as ncol(WP$df)
. This can be seen here:
length(mtcars)
# [1] 11
ncol(mtcars)
# [1] 11
nrow(mtcars)
# [1] 32
ifelse(TRUE, mtcars, iris)
# [[1]]
# [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4 14.7 32.4
# [19] 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7 15.0 21.4
That is the first column (as a list
) of mtcars
. (It might be helpful to know that a data.frame
is really just a list
where each element is the same length. In traditional ways, each element is a vector
, but more complicated objects ("list-columns") can be had as well.)
It is often assumed that the lengths of the test=
, yes=
, and no=
arguments to ifelse
are either all of the same length or of length 1 (which allows recycling). But this is neither tested nor enforced:
ifelse(TRUE, 1:2, 11:13)
# [1] 1
ifelse(c(FALSE, TRUE), 1, 11:13)
# [1] 11 1ifelse(c(FALSE, TRUE, FALSE), 1, 11:12)
# [1] 11 1 11
From this, it can be inferred that the objects are recycled as much as required to fill out to the length of test=
.
So in your case, your ifelse(is.null(df), WP$df, df2)
is returning just the first column of one of the two.
Something else about your code: don't use return
.
I suggest your code should be
observe({
print("UPDATING COORDS")
print(input$map_marker_dragend)
id <- input$map_marker_dragend$id
lat_nova <- input$map_marker_dragend$lat
lon_nova <- input$map_marker_dragend$lng
print(lat_nova)
print(lon_nova)
print(WP$df$latitude)
if (is.null(df2)) df2 <- WP$df
df2$latitude[which(WP$df$id == id)] <- lat_nova
df2$longitude[which(WP$df$id == id)] <- lon_nova
print(df2$latitude)
print(df2, width = Inf)
# declaring to later use
WP$df2 = df2
})
(I'm assuming WP
is from reactiveValues
, otherwise the assignment on the last line will not be saved.)
Upvotes: 1