I'm able to create Instances from a list of objects like below using the Weka library https://weka.sourceforge.io/doc.dev/overview-summary.html
public static Instances createWekaInstances(List<Ticket> tickets, String name) {
// Create numeric attributes "x" and "y" and "z"
Attribute x = new Attribute("x"); //sqrt of row pos
Attribute y = new Attribute("y"); // section cv
// Create arrayList of the above attributes
ArrayList<Attribute> attributes = new ArrayList<Attribute>();
attributes.add(x);
attributes.add(y);
// Create the empty datasets "ticketInstances" with above attributes
Instances ticketInstances = new Instances(name, attributes, 0);
ticketInstances.setClassIndex(ticketInstances.numAttributes() - 1);
for (Ticket ticket : tickets) {
// Create empty instance with attribute values
Instance inst = new DenseInstance(ticketInstances.numAttributes());
// get the Ticket
Ticket t = ticket;
// Set instance's values for the attributes "x", "y" and so on
inst.setValue(x, Math.sqrt(t.getRowPosition()));
inst.setValue(y, t.getSectionCVS());
// Set instance's dataset to be the dataset "ticketInstances"
inst.setDataset(ticketInstances);
// Add the Instance to Instance
ticketInstances.add(inst);
}
return ticketInstances;
}
I'm able to do a nearest neighbor search of whatever instance I want to see it's K nearest neighbors using https://weka.sourceforge.io/doc.dev/weka/core/neighboursearch/NearestNeighbourSearch.html.
Instances neighbors = tree.kNearestNeighbours(ticketInstances.get(indexToSearch), 2);
However it returns a list of 2 instances where an instance looks like -> {0 2.44949,1 0.4} so there is no way for me to associate it to my object. So is there a "Weka" way of attaching an ID or something so I'd be able to know which Object is nearest to the target object in this list of instances?
UPDATE
Okay doing this seems to work for my use case
BallTree bTree = new BallTree();
try{
bTree.setInstances(dataset);
EuclideanDistance euclideanDistance = new EuclideanDistance();
euclideanDistance.setDontNormalize(true);
euclideanDistance.setAttributeIndices("2-last");
euclideanDistance.setInstances(dataset);
bTree.setDistanceFunction(euclideanDistance);
} catch(Exception e){
e.printStackTrace();
}
Weka has not concept of unique IDs for weka.core.Instance objects, instead you need to create an additional attribute that will allow you to identify your rows (e.g., the ticket ID or a numeric attribute with unique values).
You can use the AddID filter to add a numeric attribute to your dataset that will contain such an ID, as mentioned in the Weka wiki article on Instance ID.
From your code it seems that you are just using the nearest neighbor search without any classifier or cluster involved (for these, you would use the FilteredClassifier/FilteredClusterer approach to remove the ID attribute from the data that is used for building the model), therefore you need to specify in the DistanceFunction which attributes to use for the distance calculation. This is done by supplying an attribute range to the setAttributeIndices(String) method. If your ID attribute is the first one, then you would use 2-last.
Related
I am wondering weather there is a better solution to my problem.
Better in the sense that not every object of the class Segment has to create a new database object.
I am trying to keep only one database in my program because the database is very big and I am sure there is a more efficient solution to this.
The Database holds objects of the class SegmentInformetion in a List. Each Object contains many informations each Segment object needs for its instantiation.
The Layer Class contains a List of Segments. The Layers Constructor contains an array with IDs. Every Segment will get its Information from the Database depending on the ID with which it is calling the Database.
Database {
List<SegmentInformation> segInfoList;
public SegmentInformation getSegInfos( int id ){
return segInfoList.get(id);
}
}
Layer{
List<Segments> segmentList;
public Layer( int[] segmentIDs ){
for (int i : segmentIDs){
segmentList.add( new Segment( segmentIDs[i] ) );
}
}
}
Segment{
double value1;
//....
double valuenN;
public Segment(int sID){
Database db = new Database();
SegmentInformation info = db.getSegInfos( sID );
value1 = info.getValue1();
//....
valueN = info.getValueN();
}
}
I am trying to avoid a global static variable which contains the Database.
Any suggestions for a more suitable way to instantiate all the Segment objects?
Use a Singleton to contain all the Segment objects:
In software engineering, the singleton pattern is a software design
pattern that restricts the instantiation of a class to one "single"
instance. This is useful when exactly one object is needed to
coordinate actions across the system. The term comes from the
mathematical concept of a singleton.
https://en.wikipedia.org/wiki/Singleton_pattern
I'm POSITIVE that my title for this topic is not appropriate. Let me explain. The purpose of this is to duplicate a "Profile" application, where I have a profile and so would you. We both have our own followers and in this example, we both follow each other. What this method is needed to return is a cross reference based on whom you follow that I do not. I need this method to return to me a recommended Profile object that I do not already have in my array. Right now I'm having a difficult time with one line of code within a particular method.
One of my classes is a Set class that implements a SetInterface (provided by my professor) and also my Profile class that implements a ProfileInterface which was also provided. In my code for the Profile class, I have the following object: private Set<ProfileInterface> followBag = new Set<ProfileInterface>(); which utilizes the Array bag methods from my Set class with the ProfileInterface methods I've made.
Here is the method (not complete but can't move further without my problem being explained):
public ProfileInterface recommend(){
Set<ProfileInterface> recommended;
ProfileInterface thisProfile = new Profile();
for(int index = 0; index < followBag.getCurrentSize(); index++){
Set<ProfileInterface> follows = followBag[index].toArray();
for(int followedFollowers = 0; followedFollowers < follows.getCurrentSize(); followedFollowers++) {
if()
//if Profile's do not match, set recommended == the Profile
}
}
return recommended;
}
The purpose of this method is to parse through an array (Profile as this example) and then take each of those sub-Profiles and do a similar action. The reason for this much like "Twitter", "Facebook", or "LinkedIn"; where each Profile has followers. This method is meant to look through the highest Profiles follows and see if those subProfiles have any followers that aren't being followed by the highest one. This method is then meant to return that Profile as a recommended one to be followed. This is my first dealing with Array Bag data structures, as well as with generics. Through "IntelliJ", I'm receiving errors with the line Set<ProfileInterface> follows = followBag[index].toArray();. Let me explain the reason for this line. What I'm trying to do is take "my" profile (in this example), and see who I'm following. For each followed profile (or followBag[index]) I wish to see if followBag[index][index] == followBag[index] and continue to parse the array to see if it matches. But, due to my confusion with generics and array bag data structures, I'm having major difficulties figuring this out.
I'd like to do the following:
//for all of my followers
//look at a particular followed profile
//look at all of that profile's followers
//if they match one of my followers, do nothing
//else
//if they don't match, recommend that profile
//return that profile or null
My problem is that I do not know how to appropriately create an object of a Profile type that will allow me to return this object
(in my method above, the line Set<ProfileInterface> follows = followBag[index].toArray();)
I'm trying to make an index of my Profile set to an object that can later be compared where my difficulties are. I'd really appreciate any insight into how this should be done.
Much appreciated for all help and Cheers!
When you do:
Set<ProfileInterface> follows = followBag[index].toArray();
you're trying to use Set as Array. But you can't.
Java will not allow, because Set and Array are different classes, and Set does not support [] syntax.
That is why you get error. For usefollowBag as Array you have to convert it:
ProfileInterface[] profileArray = followBag.toArray(new ProfileInterface[followBag.size()]);
for(int i=0; i<profileArray.length; i++){
ProfileInterface profile = profileArray[i];
//do what you would like to do with array item
}
I believe, in your case, you don't need assign Set object to generic Array at all. Because you can enumerate Set as is.
public class Profile {
private Set<ProfileInterface> followBag = new HashSet<Profile>();
...
public Set<ProfileInterface> recommended(){
Set<ProfileInterface> recommendSet = new HashSet<ProfileInterface>();
for(Profile follower : followBag){
for(Profile subfollower : follower.followBag){
if(!this.followBag.contains(subfollower)){
recommendSet.add(subfollower);
}
}
}
return recommendSet;
}
}
I also added possibility of returning list of recommended profiles, because there is may be several.
I've got a problem with setting the destination class for Instance object.
Imagine such situation: I've got two regression results (containing slope and intercept)
Given that, I set first four attributes to some doubles, and the last attribute, which is the destination attribute is set by the index, not by the value.
Here's how it looks like in code:
for (RegressionArffRow row : input) {
Instance record = new SparseInstance(attrInfo.size());
int attrIdx = 0;
for (RegressionResult regResult : row.getRegressionResults()) {
record.setValue(attrIdx++, regResult.getSlope());
record.setValue(attrIdx++, regResult.getIntercept());
}
record.setValue(attrIdx, row.getDestinationClass());
instances.add(record);
}
Returned destination class is in fact a class index. I've got two classes:
"flower" and "tree" created by below snippet:
FastVector destValues = new FastVector();
destValues.addElement("tree");
destValues.addElement("flower");
Attribute destClassAttribute = new Attribute("destClass", destValues);
And here comes the problem - when I set the record destination class to '1' I have my Instance set to "flower". But when I set the record to '0' the last attribute is not set at all.
Shortly it looks like that:
record.setValue(attrIdx, 0);
gives such result in debugger:
{0 0.07017,1 -1.338295,2 -0.252162,3 1.377695}
and this:
record.setValue(attrIdx, 1);
gives the following:
{0 0.07017,1 -1.338295,2 -0.252162,3 1.377695, 4 "flower"}
Ok, the problem here is that I use SparseInstance here, which is cutting values which equal 0. I intuitively thought that it concerns only numeric attributes - and only their values are being erased - no affect to nominal ones. But I've missed this fragment in documentation:
this also includes nominal attributes -- the first nominal value (i.e.
that which has index 0) will not require explicit storage, so
rearrange your nominal attribute value orderings if necessary
In my example, the "tree" value was not inserted, because its index equals 0
If you want to hold each of your nominal value, be sure that you will overcome it (if you still want to use SparseInstance)
You may want to implement it this way:
FastVector destValues = new FastVector();
destValues.addElement("dummy");
destValues.addElement("tree");
destValues.addElement("flower");
Attribute destClassAttribute = new Attribute("destClass", destValues);
and then you will never use the "dummy" destination class.
As you can see this "zero-cutting" is performed on destination class attribute as well.
I have a Table whose DataSource is set to a IndexedContainer. I also have multiple selection enabled on my Table. The Question is, how do I get all the selected values.. as an array perhaps?
My IndexedContainer:
private void populateAnalyteTable () {
Analyte[] analytes = Analyte.getAnalytes();
for (Analyte analyte : analytes) {
Object id = ic_analytes.addItem();
ic_analytes.getContainerProperty(id, "ID").setValue(analyte.getId());
ic_analytes.getContainerProperty(id, "Analyte Name").setValue(analyte.getAnalyteName());
}
// Bind indexed container to table
tbl_analytes.setContainerDataSource(ic_analytes);
}
What I'm eventually trying to get is an array of Analyte objects
Why do you want to use IndexContainer? Why don't you use BeanItemCotainer?
Please find the snippet of code below
table.setMultiSelect(true);
BeanItemContainer<Analyte> container = new BeanItemContainer<Analyte>(Analyte.class);
container.addAll(Arrays.asList(Analyte.getAnalytes()));
table.setContainerDatasource(container);
// Add some Properties of Analyte class that you want to be shown to user
table.setVisibleColumns(new Object[]{"ID","Analyte Name"});
//User selects Multiple Values, mind you this is an Unmodifiable Collection
Set<Analyte> selectedValues = (Set<Analyte>)table.getValue();
Please let me know in case it doesn't solve the issue
The vaadin objects supporting MultiSelect all return a set of the selected items.
https://www.vaadin.com/api/com/vaadin/ui/AbstractSelect.html#getValue%28%29
The drawback of this, if you need the selected items in "real" order (as displayed onscreen)
you will then have to find them from the Set to the Container
Just add your object as the Item-ID, like luuksen already propesed. Just change the initialisation of yout IndexedContainer to:
for (Analyte analyte : analytes) {
Object id = ic_analytes.addItem(analyte);
ic_analytes.getContainerProperty(id, "ID").setValue(analyte.getId());
ic_analytes.getContainerProperty(id, "Analyte Name").setValue(analyte.getAnalyteName());
}
table.getValue() is what you are looking for.
This method gives you an Object (if table is single select) or a Set<Object> (if multiselect) of the ID(s) of selected item(s). Runtime type depends on runtime id type, but if you do not need the value you can go around with Object .
If you are looking for Analytes as an array you can do
#SuppressWarnings("unchecked")
Set<Object> selectedIds = (Set<Object>) tbl_analytes.getValue();
List<Analyte> listAnalytes = new ArrayList<Analyte>();
for (Object id : selectedIds) {
listAnalytes.get(tbl_analytes.getItem(id));
}
listAnalytes.toArray();
Note that this approach works with every standard container you may use in Vaadin.
Regards!
EDIT: actually what .getValue() returns depends on the used container. In most of the cases it's the ID.
I am working with a dual-axis stacked bar graph (ADF component) using a List of objects containing the x-axis labels and the values to be displayed/stacked in the graph.
I'm relatively new to ADF & EJB so I want to apologise in advance if this question seems rudimentary to any of you.
I should mention that I'm using JDeveloper 11.1.1.5
I'm having a hard time with retrieving the value from a variable to be assigned to a property of the bar graph I'm trying to display on my JSF page.
I have briefly summarised the logic below for reference.
The data/list is retrieved from the following class data control:
public class ActivityChart {
private Double axisScale;
public ActivityChart() {
super();
axisScale = 0.0;
}
public List<ActivityDTO> getActivityDetail(List<String> businessUnits) {
List<ActivityDTO> returnNewList = new ArrayList<ActivityDTO>();
List<TransactionDTO> dataList = new ArrayList<TransactionDTO>();
TransactionSessionBean transBean = lookupTransactionSessionBean();
if (businessUnits != null && !businessUnits.isEmpty()){
dataList = transBean.getActivityData(SystemUtil.getCurrentUser(), businessUnits);
returnNewList = processTransactions(dataList);
axisScale = calcAxisScale(returnNewList);
}
return returnNewList;
}
...
The TransactionDTO object is basically a mirror of the entity object to store the fields from the queried db transactions.
The ActivityDTO object contains a String value (x-axis label) and 3 Double values for the values required for the bar graph.
What I'm trying to do is dynamically set the scale for the 2 y-axes (I'm using a dual-axis stacked bar graph) because the auto calculated values are not aligned.
Right now I've got the two relevant elements of the bar graph hard-coded with a specific axis value:
<dvt:y1Axis axisMaxAutoScaled="false" axisMaxValue="100.0"/>
<dvt:y2Axis axisMaxAutoScaled="false" axisMaxValue="100.0"/>
The value I want to use for the Y-axis is calculated and stored in the "axisScale" variable in the above class.
Really at a loss of how to move forward from here.
Would very much appreciate any guidance/direction offered.
Thanks,
Karim
Add a getter for axisScale & regenerate your data control. Add a binding for axisScale to your page & then use that as your maximum value.
The pageDef:
<attributeValues IterBinding="ActivityChartIterator" id="axisScale">
<AttrNames>
<Item Value="axisScale"/>
</AttrNames>
</attributeValues>
The page:
<dvt:y1Axis axisMaxValue="#{bindings.axisScale.attributeValue}" axisMaxAutoScaled="false"/>
<dvt:y2Axis axisMaxValue="#{bindings.axisScale.attributeValue}" axisMaxAutoScaled="false"/>