addControls for a pieChart using nPlot() in rChart - rcharts

Is addControls() compatible with type=pieChart using nPlot()?
The pie chart disappears as soon as I try to add controls.
Im attempting the following:
Sp = c("a", "b", "c", "d")
A = c(10, 4, 3, 0)
B = c(3, 5, 22, 4)
C = c(1, 0 ,10, 8)
df = data.frame(Sp, A, B, C)
p1 <- nPlot(x = "Sp", y ="A" ,
color = 'Sp', data = df, type = 'pieChart')
p1$addControls('y', 'A', values=c('A','B','C'))
p1
It works perfectly if I use multiBarHorizontalChart instead.
Thank you!

On further investigation, I realized that this is a bug in rCharts, which has been fixed on the dev branch. You can install it using devtools::install_github('ramnathv/rCharts#dev').
So running the code below will produce this chart with controls
library(rCharts)
Sp = c("a", "b", "c", "d")
A = c(10, 4, 3, 0)
B = c(3, 5, 22, 4)
C = c(1, 0 ,10, 8)
df = data.frame(Sp, A, B, C)
p1 <- nPlot(x = "Sp", y ="A" , data = df,
group = 'Sp', type = 'pieChart'
)
p1$addControls('y', 'A', values=c('A','B','C'))
p1

Related

Lua shuffle with repeating cycle

Having some Lua trouble with a a modification of Fisher-Yates shuffle in place. For example, let's say I have a 16 item table (sequence). I want to shuffle integers 1-4 then apply the shuffled pattern in the table to 1-4, 5-8, 9-12, 13-16. So:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
with a 4 item shuffling pattern of 4,2,3,1 would become:
{ 4, 2, 3, 1, 8, 6, 7, 5, 12, 10, 11, 9, 16, 14, 15, 13 }
The code here is from context and includes the "rising edge" input I am using to reshuffle. If you look at the test pic below you can see that yes, it shuffles each section in place, but it reshuffles each section -- I want the shuffled pattern to repeat.
t = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
range = 4
local function ShuffleInPlace(t)
for i = #t, 2, -1 do
local j = math.random(1, range)
local k = (math.floor(i/(range+.001)))*range + j
t[i], t[j] = t[j], t[i]
end
end
-- initialize new table for shuffling
if s == nil then s = {} end
-- use gate rising edge to shuffle
if prev == nil then prev = 0 end
if gate > 0 and prev <= 0 then
s = t
ShuffleInPlace(s)
end
prev = gate
Test pic:
LMD, thank you, your helpful reply is uncovering a solution (by creating the shuffled "pattern" sequence first, outside the iterator). (Still some issues with the first value I'm working out. And I might be looking at some biproducts of the not-so-great math.random function, but that's another story). I'm a novice so any suggestions are appreciated!
-- range input is 0 to 1
seqRange = math.floor(range*(#t*.99))
local function ShuffleRange(x)
if rdm == nil then rdm = {} end
for m = 1, x do rdm[m] = m end
for m = #rdm, 2, -1 do
local j = math.random(m)
rdm[m], rdm[j] = rdm[j], rdm[m]
return rdm[m]
end
end
local function ShuffleInPlace(t)
y = ShuffleRange(seqRange)
for i = #t, 2, -1 do
local j = (math.floor(i/(seqRange*1.001)))*seqRange + y
t[i], t[j] = t[j], t[i]
end
end
Here's how I would do it, implementing the simple approach of first generating a series of swaps and then applying that to the sublists of length n:
math.randomseed(os.time()) -- seed the random
local t = {}; for i = 1, 16 do t[i] = i end -- build table
local n = 4 -- size of subtables
local swaps = {} -- list of swaps of offsets (0-based)
for i = 0, n - 1 do
-- Insert swap into list of swaps to carry out
local j = math.random(i, n - 1)
table.insert(swaps, {i, j})
end
-- Apply swaps to every subtable from i to i + n
for i = 1, #t, n do
for _, swap in ipairs(swaps) do
-- Swap: First add offsets swap[1] & swap[2] respectively
local a, b = i + swap[1], i + swap[2]
t[a], t[b] = t[b], t[a]
end
end
print(table.concat(t, ", "))
Example output: 4, 2, 1, 3, 8, 6, 5, 7, 12, 10, 9, 11, 16, 14, 13, 15

Crosstalk links broken by second Leaflet addCircleMarkers call

I am working with multivariant data linking Leaflet and d3scatter plots. It works well for one variable. If I try to include a second variable in Leaflet by a second addCircleMarkers and addLayersControl then the sharedData links break, the filtering doesn't work and the brushing doesn't work. Thanks in advance.
A MWE is attached:
library("crosstalk")
library("d3scatter")
library("leaflet")
Long <- c(117.4,117.5,117.6)
Lat<- c(-33.7,-33.8,-33.9)
var1 <- c(21,22,23)
var2 <- c(31,32,33)
species <- c(8,9,10)
df1<- data.frame(Long, Lat, var1, var2, species)
sdf1 <- SharedData$new(df1)
col_1 <- c( "yellow" ,"black" ,"orange")
col_2 <- c("red" ,"green" ,"blue")
l <- leaflet(sdf1)%>%
setView(117.5, -33.8, 10) %>%
addCircleMarkers(radius = 1, color = col_1, group = "1") %>%
# addCircleMarkers(radius = 1, color = col_2, group = "2") %>%
# PROBLEM - adding the second "addCircleMarkers" enables the overlayGroups but
# it breaks the link between the plots and breaks the filter
addLayersControl(overlayGroups=c("1","2"))
m <- list(l, filter_checkbox("unique_id_for_species", "Animal Species", sdf1, ~species))
n <- list(d3scatter(sdf1, ~var2, ~var1, color = ~species, x_lim = c(30,40), y_lim = c(20,25), width="70%", height=200),
d3scatter(sdf1, ~var1, ~var2, color = ~species, y_lim = c(30,40), x_lim = c(20,25), width="70%", height=200))
bscols(m, n)

Get index of a value in a table which already has a key (pick a random key/value pair)

I'm looking to pick a random key/value pair from a table, but using math.random() doesn't work.
--intialises randomization
math.randomseed(os.time()+30) --sets a random seed based on the time
math.random(); math.random(); math.random(); --clears presets
local phrases = {
["a"] = 3
["b"] = 7
["d"] = 4
["f"] = 8
["p"] = 5
}
local phrase = phrases[math.random(1,5)]
phrase would always output as nil. Is there a method of getting the index to use with math.random() or an alternate method I could use?
math.random(1, 5) returns numbers from 1 to 5. Your keys are strings.
You could create a table (as in: array - integer keys), get a random key from there and then access the phrases:
local phrases = {
["a"] = 3,
["b"] = 7,
["d"] = 4,
["f"] = 8,
["p"] = 5
}
local keys = {}
for k in pairs(phrases) do
table.insert(keys, k)
end
local random_key = keys[math.random(1,5)] -- One of: "a", "b", "d", "f", "p"
local phrase = phrases[random_key] -- One of: 3, 7, 4, 8, 5

Lua: 'for' loop problems (string.gsub)

I'm making a lua script for custom encrypting a string, but I can't find a loop that substitutes the letter to a number correspondent to the alphabet table.
It must return something like this:
"hello"
> 8, 4, 12, 12, 15
That'll be the first part of the encryption proccess but I can't program such a loop, any help? (Script below:)
local text = "what"
local key = math.random(100000, 500000)
local pie = math.pi
local n = 26
local alpha = { a = 1, b = 2, c = 3, d = 4, e = 5, f = 6 , g = 7, h = 8, i = 9, j = 10,
k = 11, l = 12, m = 13, n = 14, o = 15, p = 16, q = 17, r = 18, s = 19, t = 20, u = 21, v = 22, w = 23, x = 24, y = 25, z = 26}
function enumerate(str)
return str:gsub("%l", function(c) return c.char(c:byte()-96) end):byte(1,-1)
end
UPDATE: New question, how do I return the numbers as:
46, 68, 46, 32, 4, 12, 18, 15, 23, 32, 15, 23, 5, 8
Instead of a string or with whitespaces:
"46 68 46 32 4 12 18 15 23 32 15 23 5 8"
You just have to collect each char on a table with explode + encode (see below) and then call unpack (or table.unpack) to get a tuple.
First explode:
function explode(str)
local ret = {}
for c in str:gmatch(".") do
table.insert(ret, c)
end
return ret
end
The encoding part can be done this way:
local BASE_CHAR = ("a"):byte()
function encode(c)
return c:byte() - BASE_CHAR + 1
end
Putting everything together:
unpack = unpack or table.unpack -- Handling lua 5.1 or higher
function enumerate(str) -- Keeping the original name
local exploded = {}
for i, c in ipairs(explode(str)) do
exploded[i] = encode(c)
end
return unpack(exploded)
end
And a test:
print(enumerate("test"))
Which yields the following result:
20 5 19 20
Note:
I prefer to keep results in table and only unpack if necessary. This way you can manipulate the table the way you want and it's more convenient than dealing with tuples:
function enumerate(str) -- Keeping the original name
local exploded = {}
for i, c in ipairs(explode(str)) do
exploded[i] = encode(c)
end
return exploded
end
print(unpack(enumerate("test")))
And if you want a string:
print(table.concat(enumerate("test"), ", "))
Hope this solves the problem

How do you do the Fisher-Yates shuffle in Lua

I've been asking questions on random numbers, and I decide the Fisher-Yates shuffle would be the best option. I make a table 't'
t = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
Now, how would I even shuffle these and be able to use them individually, for example generate the results in another table u
u = {}
For those that find this answer later, this will shuffle in place without making a new table:
local function ShuffleInPlace(t)
for i = #t, 2, -1 do
local j = math.random(i)
t[i], t[j] = t[j], t[i]
end
end
And this one that returns a shuffled table without touching the original (unlike the current answer, which both shuffles in-place and returns a copy):
local function Shuffle(t)
local s = {}
for i = 1, #t do s[i] = t[i] end
for i = #t, 2, -1 do
local j = math.random(i)
s[i], s[j] = s[j], s[i]
end
return s
end
Usage:
local t = {"a", "b", "c", "d", "e", "f"}
print(table.concat(t)) --> abcdef
local s = Shuffle(t)
print(table.concat(t)) --> abcdef (unchanged)
print(table.concat(s)) --> fbcade (shuffled)
ShuffleInPlace(t)
print(table.concat(t)) --> dcbfea (shuffled)
And a quick sanity check that they're uniform:
local t = {"a", "b", "c"}
local results = {abc = 0,acb = 0,bac = 0,bca = 0,cab = 0,cba = 0}
for i = 1, 10000000 do
ShuffleInPlace(t)
local r = table.concat(t)
results[r] = results[r] + 1
end
for k, v in pairs(results) do print(k, v) end
--[[
cba 1667473
cab 1666235
bca 1665672
bac 1666782
acb 1666447
abc 1667391
--]]
NOTE: Check the other answer https://stackoverflow.com/a/68486276/1190388 which fixes an issue in the code snippet below as well as providing other alternatives
If you do not have holes in your table:
math.randomseed(os.time()) -- so that the results are always different
function FYShuffle( tInput )
local tReturn = {}
for i = #tInput, 1, -1 do
local j = math.random(i)
tInput[i], tInput[j] = tInput[j], tInput[i]
table.insert(tReturn, tInput[i])
end
return tReturn
end

Resources