How to format scientific data into proper data series for graph display in Ruby (Rails 3.1.x)? - ruby-on-rails

Needing some guidance about how to properly graph data that is very small and stored as BigDecimal.
If anyone has had experience using BigDecimals in any graphing scenario I believe your input on how you placed these into a usable sequence would be invaluable.
Presently I'm using lazy_high_charts and it really seems that this is going to work out exceptionally well, however I've run into a hitch where I've not dealt with data on the minute BigDecimal scale hitherto.
Given my queries, I'll be pulling out about a 1,000 data points for a few different series of data ranging in accuracy from about 0.100E-9 to about 0.100E-1.
What would be the best way to prep these data series for presentation in such a graph that has a scientific application and therefore precision is important? I'm not sure if I could or should continue in BigDecimal or something else?
I'm presently querying the database with a line similar to:
series_a = dataset.order("date").select('data_set.data1').limit(1000).all.zip
I'd appreciate some guidance of going from this result (again, the output is an array of BigDecimals) to the appropriate format for what will go into the chart series.
An contextual example of the code I'm using to build the chart in my controller is:
#h = LazyHighCharts::HighChart.new('graph') do |f|
series_a = dataset.order("date").select('data_set.data1').limit(1000).all.zip
series_b = dataset.order("date").select('data_set.data3').limit(1000).all.zip
f.series(:name => 'Data 1', :data => series_a)
f.series(:name => 'Data 2', :data => series_b)
f.chart({:defaultSeriesType => "line" })
f.yAxis [
{:title => { :text => "Left Y Label", :margin => 10} },
{:title => { :text => "Right Y Label"}, :opposite => true }
]
f.xAxis(:title => { :text => "X Label"} )
f.title(:text => "Graph Title")
f.legend(:align => 'right', :verticalAlign => 'top', :y => 75, :x => -50, :layout => 'vertical')
end
I think I'm a bit further along in my understanding of this having decided to convert the BigDecimals to strings as per "How to access fields by attribute name from ActiveRecord row results?" However it appears ultimately this fails and gives erratic results as the series functions :data field expects, I think, numeric input. I am thinking that this ultimately emits json to highcharts, however I'm still stuck for the moment in my attempt to pass these values on in correctly.

When you do this:
series_a = dataset.order("date").select('data_set.data1').limit(1000).all.zip
you'll end up with an array of arrays as we already discussed elsewhere. If you get rid of the zip, you should end up with an array of objects in series_a. I'd guess that chart would be happier with an array of numbers so:
series_a = dataset.order("date").
select('data_set.data1').
limit(1000).
all.
map(&:data1)
or, if data1 is a BigDecimal (due to using a fixed precision type in the database) then maybe you'd want this:
series_a = dataset.order("date").
select('data_set.data1').
limit(1000).
all.
map { |o| o.data1.to_f }
to get an array of floating point values that the chart should know what to do with.
I'm not familiar with Highcharts so there is some guesswork here.

Related

Inverted Axis in AXLSX Bar Chart

I'm using this very straightforward code (practically the same as the bar chart examples here, however I am noticing that the Axes are inverted. The data that should be on the Val axis is shown on the Cat axis.
This is also true for the example linked above, and I can't seem to find a way to put them in the correct order.
Below is an image of the problem. The code used to generate it is:
sheet.add_chart(Axlsx::Bar3DChart,:title => "Chart", :show_legend => false, :start_at => "A1", :end_at => "P30", :bar_dir => :col) do |chart|
chart.add_series :data => sheet["B1:B25"], :labels => sheet["A1:A25"]
chart.valAxis.gridlines = false
chart.catAxis.gridlines = false
end
I fixed it. You can find my fork of axlsx here: https://github.com/HansCz/axlsx.
A pull request will be sent to https://github.com/randym/axlsx

Nokogiri- creating a hash for each scraped result

I am attempting to create a hash for each result that matches my css selector. As it stands, there are about 10 results per page, but I would like to create a hash for each of these results. What would be the best way going about this?
Or perhaps it makes sense to limit the number of results found in nokogiri?
listing_data = #nodes
listing = {
:url => listing_data.css('div#content div.content_inner div.section div.supercolumn div.column div.block div.items div#pages div.unsponsored div.item.compact div.item_inner div.photo a img.tiny').text,
:price => listing_data.css('div#content div.content_inner div.section div.supercolumn div.column div.block div.items div#pages div.unsponsored div.item.compact div.item_inner div.more h3 span').text
}
end
So listing_data.css returns an Array (or something similar) of results? Rough code sketch here:
urls = listing_data.css('selector here')
prices = listing_data.css('another selector')
result = urls.zip(prices).map do |url,price|
{:url => url, :price => price}
end

How do I convert an array of strings into a comma-separated string?

I have an array:
array = ["10", "20", "50", "99"]
And I want to convert it into a simple comma-separated string list like this:
"10", "20", "50", "99"
array.join(',') will almost do what you want; it will not retain the quotes around the values nor the spaces after.
For retaining quotes and spaces: array.map{|item| %Q{"#{item}"}}.join(', ')
This will print "\"10\", \"20\", \"50\", \"99\"". The escaped quotes are necessary assuming the question does in fact call for a single string.
Documentation on the %Q: string literals.
You could use inspect as suggested in another answer, I'd say that's personal preference. I wouldn't, go look at the source code for that and choose for yourself.
Useful aside: array.to_sentence will give you a "1, 2, 3 and 4" style output, which can be nice!
["10", "20", "50","99"].map(&:inspect).join(', ') # => '"10", "20", "50", "99"'
Here:
array.map {|str| "\"#{str}\""}.join(',')
Several answers have offered solutions using #map, #inspect, #join. All of them fail to get certain details of CSV encoding correct for edge cases involving embedded commas and/or string delimiters in the elements.
It's probably a better idea to use the stdlib class CSV then to roll your own.
irb> require 'csv'
=> true
irb> a = [10,'1,234','J.R. "Bob" Dobbs',3.14159]
=> [10, "1,234", "J.R. \"Bob\" Dobbs", 3.14159]
irb> puts a.to_csv
10,"1,234","J.R. ""Bob"" Dobbs",3.14159
The map.join solutions are sufficient if this encoding doesn't need to care about embedded delimiters, or is intended for some internal representation only, but they will fail if generating data for exchange with other programs that expect Comma Separated Values (CSV) as a generally understood representation.
The simplest solution is to use the built in ".to_sentence" method.
So
["fred", "john", "amy"].to_sentence outputs "fred, john, and amy"
This is a slightly alternative solution, particularly handy if you need to convert an array with double quoted strings to a single quoted list (for say SQL queries):
"'#{["John Oliver", "Sam Tom"].join("','")}'"
to
'John Oliver', 'Sam Tom'
Attribution: https://alok-anand-ror.blogspot.com/2014/04/ruby-join-array-elements-with-single.html
This is how you can send push notifications using FCM for Android devices.
Assuming you want notify followers when ever a user posts something on their status this is how you do it. This is done in Rails 5.2.6 for Rest Apis--- But still you can use the same for web push notifications. This is for sending to many devices with registration_ids to target followers with notifications.
Gem : fcm
in your controller:
require "fcm"
def create_vibe(user)
#vibe = user.vibes.new(content: #content, picture: #picture, video: #video, isvideofile: #isvideofile, video_thumbnail: #video_thumbnail, source: #source, background_color: #background_color)
#followed = user.followers
if #followed.present?
#registration = #followed.map { |s| s.registration_id }
end
if #vibe.save
fcm = FCM.new("") # set your FCM_SERVER_KEY
options = {
data: {
notification_type: 1,
title: "#{#vibe.user.username} " "has posted a new Vibe",
body: "#{#vibe.content}",
user_data: {
vibe_id: #vibe.id,
user_id: #vibe.user.id,
background_color: #background_color,
},
},
}
response = fcm.send(#registration, options)
puts response
render :status => 200,
:json => { :success => true,
:info => "Vibe posted successfully",
:vibe_info => {
:content => #content,
:picture => #picture,
:video => #video,
:video_thumbnail => #video_thumbnail,
:isvideofile => #isvideofile,
:source => #source,
:fcm => options,
} }
else
render :status => 200, :json => { :success => false, :result => "Vibe can't be blank" }
end
end

Use different color for different values in drop down for excel files created

I need to create an excel sheet with a field status. It is a drop down with values 'High', 'Medium', and 'Low'. I need to show different colors when they select different values. I have implemented the drop down using writeexcel gem. Here is my code:
worksheet.data_validation(count, 5,
{
:validate => 'list',
:source => ['High', 'Medium', 'Low'],
})
The drop down is working fine. But I want to specify a color for each selection. I can color the cell based on the selection of the dropdown, but what I need is different colors for different selections of the drop down. Any other gem having this implementation is also fine.
The write_xlsx gem is an updated version of writeexcel that supports the newer Excel 2007+ XLSX format. It is by the same author and has the same interface but has additional features.
One of these new features is Conditional Formating.
You can use it to apply conditional formats to the same cell as the drop-down validation like this:
worksheet.conditional_formatting(count, 5,
{
:type => 'cell',
:format => format1,
:criteria => '=',
:value => '"High"'
}
)
worksheet.conditional_formatting(count, 5,
{
:type => 'cell',
:format => format2,
:criteria => '=',
:value => '"Medium"'
}
)
...
You will need to define the formats using the standard interface.
Note, write_xlsx is a port of the Perl module Excel::Writer::XLSX. That module contains additional documentation on the use of conditional formats. You should be able to convert the examples to Ruby easily enough.
See also my answer to your previous question.

Rails 3 - Custom JSON with Conditions

I'm trying to DRY up my code and I have two methods that do almost the same thing but add an extra fields for one instance. It is formatting JSON in Rails and trying to see if there is a way where I can perform an if statement within the result.collect similar to below. Any help is much appreciated
results.collect{ |result| { :type => defined?(result.type) ? result.type : "Total",
:jan => result.jan, :feb => result.feb, :mar => result.mar, :apr => result.apr,
:may => result.may, :jun => result.jun, :jul => result.jul, :aug => result.aug,
:sep => result.sep, :oct => result.oct, :nov => result.nov, :dec => result.dec } }
in this statement
:type => defined?(result.type) ? result.type : "Total"
I want to be able perform a check if result.type exists in the query then list it else just put "Total"
Any ideas how to perform this? Thanks everyone
I ended up writing in the method to check if with_type or not. If true then I added the type select statement in and if false then added
Select 'Total' as Type
I was hoping to figure out how to modify the json as in the question but modifying the composed_scope worked too.

Resources