Creating a function using value_counts in a for loop - function

I am attempting to create a function that calls on the value_counts function for every variable in the list that I pass through it. Admittedly, I have no idea what I am doing and have oversimplified "hello world" tutorials as an example. My sample code is attached. Thank you for your help.
data1.columns = ['Year', 'Rank', 'Company', 'Revenue', 'Profit']
def vc(*args):
for x in args:
value_counts()
return
vc(['Year', 'Rank', 'Company', 'Revenue', 'Profit'])
I have also tried
def vc(args):
for x in args:
value_counts(x)
return
vc(['Year', 'Rank', 'Company', 'Revenue', 'Profit'])
I get an error stating that value_counts is not defined.

You're not passing x to value_counts.
for x in args:
value_counts()
should be
for x in args:
value_counts(x)
Also, vc takes *args param, which means you don't need to give it a list. You can call with vc('Year', 'Rank', 'Company', 'Revenue', 'Profit'), and when you reference args inside vc you will get a list. You can call vc with a list like you are doing now, but you would change the def vc(*args) definition to vc(args) so that everything matches up.
Does this help?

Related

yii2 with dhtmlx scheduler and select populated from the server

I am trying to populate the project select dropdown with data from the server.
I am using yii2.
My controller data action:
public function actionData()
{
$list = new OptionsConnector(null, "PHPYii");
$list->render_table("project", "id", "id(value),name(label)");
$connector = new JSONSchedulerConnector(null, "PHPYii");
$connector->set_options("project", $list);
$connector->configure(
new Booking(), "id", "start, end, activity, user, subsubproject, status, comment"
);
$connector->render();
}
I get an error message:
Exception 'Error' with message 'Call to a member function find() on
string'
And I think this line is the cause: $connector->set_options("project", $list);
What should I change?
UPDATE:
So I am here now:
public function actionData() {
$list = new JSONOptionsConnector(null, "PHPYii");
$list->enable_log("text1.log");
$list->configure(
new Subsubproject(),
"-","id, name"
);
$list->render();
$connector = new JSONSchedulerConnector(null, "PHPYii");
$connector->enable_log("text2.log");
$connector->set_options("subsubprojects", $list);
$connector->configure(
new Booking(),
"id", "start, end, activity, user, subsubproject, status,comment"
);
$connector->render();
}
and I get this:
0: Object { key: undefined, id: 1, name: "Thing1", … }
​1: Object { key: undefined, id: 2, name: "Thing2", … }
​2: Object { key: undefined, id: 3, name: "Thing3", … }
I don't have keys... How can I get some? :)
1) You don't need to call the render method of JSONOptionsConnector directly. Calling it ends processing of the request if I'm not mistaken, so the SchedulerConnector takes no effect
Try commenting out $list->render(); line.
2) The response format seems a bit off. This may be a bug of PHPYii wrapper of dhtmlx connector, I'm not sure
According to source codes the client-side needs value and label properties from options, and while handler returns id and name.
You can try something following:
public function actionData() {
$list = new JSONOptionsConnector(null, "PHPYii");
$list->enable_log("text1.log");
$list->configure(
new Subsubproject(),
"id","id(value), name(label)"
// or
// "id(value)","id(value), name(label)"
);
$connector->enable_log("text2.log");
$connector->set_options("subsubprojects", $list);
$connector->configure(
new Booking(),
"id", "start, end, activity, user, subsubproject, status,comment"
);
$connector->render();
}
This should produce a json response containing a list of booking and subprojects.
However, I can't test this code so something may still be wrong.
You can try it and see whether the result JSON looks right.
If it doesn't get you any closer, I honestly would produce json manually rather than using a connector with PHPYii wrapper. That way you'll have direct control over what is returned from your controller and won't have another black box there.
You'll need to return a json of the following structure from your action:
https://docs.dhtmlx.com/scheduler/data_formats.html#jsonwithcollections
so you'll have something like this in your action:
return $this->asJson([
"data"=> $preparedEventsArray
"collections" => [
"subprojects"=> $preparedSubprojects
]
]);
where $preparedEventsArray is an array of event objects as shown in docs, and $subprojects - your value/label objects
Note that names of properties in the data collection - "id","start_date","end_date","text" - are mandatory, you'll have to map your data model to this structure,
e.g.
start -> start_date
end -> end_date
activity -> text
all other properties can have their names unchanged.
The official docs don't have a sample code for Yii2, unfortunately.
There are common docs for server formats
https://docs.dhtmlx.com/scheduler/server_integration.html
And tutorials for PHP Slim framework and Laravel, which is not exactly what you need, but the closest thing the current documentation has.

How to define variable outside method that is present inside method?

I'm trying to create a method that allows me to query SQL in ruby without typing results = client.query('code') for every query. Heres my current method but it says that results are undefined in my puts statement. When I don't use my method it works normally.
require "mysql2"
client = Mysql2::Client.new(:username => 'buck19j')
def sql(code)
client = Mysql2::Client.new(:username => 'buck19j')
results = client.query(code)
end
sql('SHOW DATABASES')
puts(results.to_a)
How to define variable outside method that is present inside method?
Make the method return the value, not assign it:
def sql(code)
client = Mysql2::Client.new(:username => 'buck19j')
client.query(code)
end
Then assign a variable when you call the method:
results = sql('SHOW DATABASES')
puts(results.to_a)
results doesn't "go out" the sql method, because is a local variable. An approach would be to define it as an instance variable, and you could use then as you do with puts (still unclear what's the whole context of this).
def sql(code)
client = Mysql2::Client.new(:username => 'buck19j')
#results = client.query(code)
end
sql('SHOW DATABASES')
puts(#results.to_a)
Other way would be just leave the function returns the client.query(code) value:
def sql(code)
client = Mysql2::Client.new(:username => 'buck19j')
client.query(code)
end
puts(sql('SHOW DATABASES').to_a)

How to set a property as an array i initial state?

In my reducer I set initial state by:
const initialState = fromJS({
results: [],
});
However if I try to print results by
initialState.get('results')
I get an immutable Map.
On the other hand if in my reducer (listening to an action) I set the array via
...
case LOAD_SUCCESS:
return state
.set('results', []);
...
the array will be an actual (non-Immutable) array after executing:
state.get('results')
(e.g. in a selector defined via reselect)
Why?
From the fromJS docs:
Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
That said, fromJS({ results: [] }) is equal to Map({ results: List([])})
as soon as you call state.set('results', []), you replace List([]) with plain array [].
This is a classical trap for new starters.
The way I see it is you have to choose to either always use List there, or plain array.
List way:
Initialize: const state = fromJS({results: []})
Reduce: return state.update("results", list => list.clear())
Array way #1:
Initialize: const state = fromJS({results: null})
INIT reduce (dispatched once, to init state) return state.set("results", [])
Reduce: return state.set("results", [1, 2, 3])
Array way #2:
Initialize: const state = Map({results: []})
Reduce: return state.set("results", [1, 2, 3])
I'd recommend to always use Array way #2. It adds more code, as you have to control List / Map for each state's field, but it guarantees you that you get exactly what you want.
In the end it comes something like this:
const initialState = Map({
results: [],
some_field_as_list: List([]),
some_field_as_map: Map([]),
... // etc
});
fromJS({ results: [] }) is equal to Map({ results: List([])}),
Using state.set('results', []) you replace List([]) with plain []
I found this helpful in this case:
Initialize: const state = fromJS({results: []})
Reduce: return state.set('results', List([1,2,3]));
It was better than using plain array because later you can use setIn function editing the same state variable:
return state.setIn(['results',state.get("results").size], nextElement);
or
return state.setIn(['results',-1], lastElement);

Appending data to JSON column - Rails 4, Postgres

Model Listing has a json column named vendors, which defaults to {}:
add_column :listings, :vendors, :json, null: false, default: {
hd: {}
...
}
end
Inside the Listing class, I am trying to merge! in a hash to hd: {..} like so:
def self.append_vendor_attrs(sku)
listing = find_by(sku: sku) || Listing.new(sku: sku)
listing.vendors[:hd].merge!({ foo: 'bar' })
listing.vendors_will_change!
listing.save! # throws no exceptions in the log
end
but vendors[:hd] remains empty. if I try to replicate this manually with:
l = Listing.create...
l.vendors[:hd].merge!({ foo:'bar' })
my hash persists.
Calling listing.vendors_will_change! tells Active Record that the value of the attribute "was" the new value. From AR's perspective, then, the old and new values match, and so the record is not dirty when you call save!.
The fix is to move listing.vendors_will_change! above the line where you modify the attribute. So the new code will look like this:
def self.append_vendor_attrs(sku)
listing = find_by(sku: sku) || Listing.new(sku: sku)
listing.vendors_will_change!
listing.vendors[:hd].merge!({ foo: 'bar' })
listing.save! # throws no exceptions in the log
end

RoR - different object_id inside after_initialize callback after obj.reload

I've written a method for my project which extends ActiveRecord models behaviour, I've stripped out most of it, consider the following code:
class ActiveRecord::Base
def self.has_translations
after_initialize :clear_translations_cache
def clear_translations_cache
binding.pry
#_translations = {}
end
end
end
Basically, I want the #_translations instance variable to get cleared when I .reload the instance from the database, but for some reason, after fetching an existing object from the database, executing a method which populates #_translations, and then executing object.reload, #_translations still contains the same data.
I know for sure that the callback gets executed when first fetching the object from database and when calling .reload. I used binding.pry to halt execution inside the callback method, but for some reason self.object_id inside .reload has a different object_id than my original object, and therefore #_translations in the original object doesn't get cleared.
Attached is the console output:
1.9.3p194 :008 > s = TranslatedItem.first
76: def clear_translations_cache
=> 77: #_translations = {}
78: end
[1] pry(#<TranslatedItem>)> self.class
=> TranslatedItem(id: integer, created_at: datetime, updated_at: datetime)
[2] pry(#<TranslatedItem>)> self.object_id
=> 70254243993580
[3] pry(#<TranslatedItem>)> exit
1.9.3p194 :009 > s.object_id
=> 70254243993580
1.9.3p194 :010 > s.reload
76: def clear_translations_cache
=> 77: #_translations = {}
78: end
[1] pry(#<ServiceLevel>)> self.class
=> TranslatedItem(id: integer, created_at: datetime, updated_at: datetime)
[2] pry(#<TranslatedItem>)> self.object_id
=> 70254259259120
I'm guessing the behavior you're seeing is related to how ActiveRecord reload works:
fresh_object = self.class.unscoped { self.class.find(self.id, options) }
#attributes.update(fresh_object.instance_variable_get('#attributes'))
You'll notice that it is creating a fresh object by finding it from the database, which explains why you are seeing two different object_id values in your callback method. The object that is initialized during the reload is only used for its attributes and then goes out of scope.
It's not clear from your question whether you were just curious why it behaved this way or if you're looking for an alternative way to do it.
Update:
You've got a few options if you're just looking for a way to clear the instance variable when you reload the model.
1) Add your own reload method that you can explicitly call:
class ActiveRecord::Base
def reload_everything
reload
#_translations = {}
end
end
object.reload_everything
2) Change the behavior of reload
module ReloadTranslations
def reload(*args)
super
#_translations = {}
end
end
ActiveRecord::Base.send(:include, ReloadTranslations)