I have derived from QAbstractItemModel to encode my own tree of data, but the QTreeView is not displaying.
Most of the answers I saw to similar questions were solved because of wrong variable life time, so here is my code for allocation of the model:
ui.tvHierarchy->setModel(
new MetaHierarchyModel(
cutOffExtension(
fileName.toStdString()
)
)
);
On construction the model gets its root node filled with data and later shall load more data as needed (via fetchMore).
I began outputting every function that is called. This is a log of the call sequence:
columnCount( QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return 1
columnCount( QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return 1
columnCount( QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return 1
hasChildren( QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return true
hasChildren( QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return true
canFetchMore( QModelIndex(-1,-1,0x0,QObject(0x0) ) ))
return false
rowCount( QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return 1
index( 0 , 0 , QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return QModelIndex(0,0,0x987aa0,MetaHierarchyModel(0xa16970) )
hasChildren( QModelIndex(0,0,0x987aa0,MetaHierarchyModel(0xa16970) ) )
return true
columnCount( QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return 1
parent( QModelIndex(0,0,0x987aa0,MetaHierarchyModel(0xa16970) ) )
return QModelIndex(-1,-1,0x0,QObject(0x0) )
index( 0 , 0 , QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return QModelIndex(0,0,0x987aa0,MetaHierarchyModel(0xa16970) )
data( QModelIndex(0,0,0x987aa0,MetaHierarchyModel(0xa16970) ) , 13 )
return "Metaparticle 1"
columnCount( QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return 1
parent( QModelIndex(0,0,0x987aa0,MetaHierarchyModel(0xa16970) ) )
return QModelIndex(-1,-1,0x0,QObject(0x0) )
index( 0 , 0 , QModelIndex(-1,-1,0x0,QObject(0x0) ) )
return QModelIndex(0,0,0x987aa0,MetaHierarchyModel(0xa16970) )
data( QModelIndex(0,0,0x987aa0,MetaHierarchyModel(0xa16970) ) , 13 )
return "Metaparticle 1"
Output of roleNames():
QHash((0, "display")(1, "decoration")(2, "edit")(3, "toolTip")(4, "statusTip")(5, "whatsThis"))
The last four lines are then repeated forever (or at least until I loose my patience).
To me it looks like the root data are fetched, but they never get displayed. It is strange, that the last parameter of data - which is int role, has the value 13, which is not defined as any role (still I give back valid strings unconditionally).
Is there anything I missed when implementing this?
The QAbstractItemModel::data function should be as stingy as possible with the data it returns. Make sure you only return data when you have an exact match on the display role and column number. In all other cases just return an invalid QVariant (just call the default constructor), and your view widget will fill in these missing values with sensible defaults.
Related
How do I calculate the percentage of values in column A from the count of column B?
Or the percentage of non-blank values from count of all values (blank and not)?
I have a column with unique IDs and a 4 columns with values, and I want to see the 4 columns together in a bar chart which I can do with count.
ID
A
B
C
D
12345
1
3
12346
1
2
3
4
12347
3
4
12348
3
4
With count it would show as A=2, B=1, C=4, D=3.
In the percentage I'm looking for it would show as A=50%, B=25%, C=100%, D=75%.
Thanks!
Maya
Achievable with following measures
_a =
DIVIDE (
CALCULATE ( COUNT ( tbl[A] ), ALL ( tbl[ID] ) ),
CALCULATE ( COUNT ( tbl[ID] ), ALL ( tbl[ID] ) )
)
_b =
DIVIDE (
CALCULATE ( COUNT ( tbl[B] ), ALL ( tbl[ID] ) ),
CALCULATE ( COUNT ( tbl[ID] ), ALL ( tbl[ID] ) )
)
_c =
DIVIDE (
CALCULATE ( COUNT ( tbl[C] ), ALL ( tbl[ID] ) ),
CALCULATE ( COUNT ( tbl[ID] ), ALL ( tbl[ID] ) )
)
_d =
DIVIDE (
CALCULATE ( COUNT ( tbl[D] ), ALL ( tbl[ID] ) ),
CALCULATE ( COUNT ( tbl[ID] ), ALL ( tbl[ID] ) )
)
Try this approach:
Create 4 formulas
A% = CONCATENATE(FORMAT((CALCULATE(COUNT(Sheet5[A]),ALLNOBLANKROW(Sheet5[A]))/COUNTROWS(ALL(Sheet5)))*100,"") , "%")
B% = CONCATENATE(FORMAT((CALCULATE(COUNT(Sheet5[B]),ALLNOBLANKROW(Sheet5[B]))/COUNTROWS(ALL(Sheet5)))*100,"") , "%")
C% = CONCATENATE(FORMAT((CALCULATE(COUNT(Sheet5[C]),ALLNOBLANKROW(Sheet5[C]))/COUNTROWS(ALL(Sheet5)))*100,"") , "%")
D% = CONCATENATE(FORMAT((CALCULATE(COUNT(Sheet5[D]),ALLNOBLANKROW(Sheet5[D]))/COUNTROWS(ALL(Sheet5)))*100,"") , "%")
End result is:
This may be a really simply one but cannot get this to work.
Invitations_Daily =
CALCULATE (
DISTINCTCOUNTNOBLANK ( AppUser[UserId] ),
USERELATIONSHIP ( AppUser[DateInvitedID], 'Date'[DateId] ),
FILTER (
'Date',
'Date'[DateId]
= SELECTEDVALUE ( 'DateSelector'[DateId], MAX ( 'DateSelector'[DateId] ) )
)
) + 0
I have a measure and want the previous days value. When I put in a -1 then ))+0 it gives me 0, instead of the previous day value. Is there something obvious I am missing or is there something else wrong with my data model etc ?
I've been trying to get the sum of the following table's column VALUE using DaxStudio in order to put that on PowerBI once is's ok, since PBI can get slow if you test a code for large calculated tables.
Table from DaxStudio
BU VALUE
------------------------
FOODS 0.0000
FIBI 0.0000
GEOS/CIS 0.7300
CASC
S_S
SGS
COCOA
COCOA/SSSA
CORPORATE
N/A
CIS
The code behind it:
DEFINE
VAR TOTAL =
CALCULATE (
SUMX (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[QUANTIDADE_ANTERIOR]
);
FILTER (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[DATE] = "2018"
&& PACKAGING_POWERBI_YEARLY_2[CODIGO] = "43130"
)
)
EVALUATE
SUMMARIZE (
CALCULATETABLE (
FILTER (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> BLANK ()
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> 0
)
);
PACKAGING_POWERBI_YEARLY_2[BU];
"VALUE"; FORMAT (
(
CALCULATE (
SUMX (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[QUANTIDADE_ANTERIOR]
);
FILTER (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[DATE] = "2018"
&& PACKAGING_POWERBI_YEARLY_2[CODIGO] = "43130"
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> BLANK ()
)
) / TOTAL
)
* (
CALCULATE (
SUMX ( PACKAGING_POWERBI_YEARLY_2; PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] );
FILTER (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[DATE] = "2018"
&& PACKAGING_POWERBI_YEARLY_2[CODIGO] = "43130"
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> BLANK ()
)
)
);
"0.0000"
)
)
Instead of generating the table I would like to sum the results of column VALUE, but the only way I got to plot a result without error is through a "CALCULATED TABLE" (above).
Every filter I try leads to an error.
The idea is to get just the sum of that calculated column VALUE:
0.7300
But every simpler filter or SUMX condition I try, an error pops-up.
I'd think you could clean it up to look something like this:
CALCULATE (
SUMX (
VALUES ( PACKAGING_POWERBI_YEARLY_2[BU] ),
SUM ( PACKAGING_POWERBI_YEARLY_2[QUANTIDADE_ANTERIOR] )
/ CALCULATE (
SUM ( PACKAGING_POWERBI_YEARLY_2[QUANTIDADE_ANTERIOR] ),
ALL ( PACKAGING_POWERBI_YEARLY_2[BU] )
)
* SUM ( PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] )
),
FILTER (
PACKAGING_POWERBI_YEARLY_2,
PACKAGING_POWERBI_YEARLY_2[DATE] = "2018"
&& PACKAGING_POWERBI_YEARLY_2[CODIGO] = "43130"
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> BLANK ()
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> 0
)
)
This uses SUMX to iterate through each of the BU values and for each one, calculates the value
(QUANTIDADE_ANTERIOR / Total QUANTIDADE_ANTERIOR ) * PRECO_PONDERADO
where the filters are reused instead of repeated.
I can't guarantee that this code works exactly as intended, but it should point you in a better direction.
Let's assume I have the below dataset.
What I need to create the below matrix where if it is the beginning or month end, I aggregate A or B in Category 1 and calculate SUM but if it is any other day in a month but 1st or last, I am tagging A or B in Category 2 and calculate SUM. I guess I need to use SWITCH, don't I?
Edit in info from comments
Like to create 3 col:
isStart = IF ( main_table[date] = STARTOFMONTH ( main_table[date] ), 1, 0 )
isEnd = IF ( main_table[date] = ENDOFMONTH ( 'main_table'[date] ), 1, 0 )
in_between_date =
IF ( AND ( main_table[date] <> ENDOFMONTH ( 'main_table'[date] ),
main_table[date] <> STARTOFMONTH ( main_table[date] ) ), 1, 0 )
Then, create the columns with my categories, like
start_end =
IF ( OR ( NOT ( ISERROR ( SEARCH ( "A", main_table[code] ) ) ),
main_table[code] = "B" ),
"Category 1",
BLANK () )
and
in_between =
IF ( OR ( main_table[code] = "B", main_table[code] = "A" ), "Category 2", BLANK () )
But then, what should I use in switch/if ? = if(VALUES('main_table'[isStart]) = 1, then what?
You where on the right track but overcomplicated a bit. You only need one extra column "Category" giving for each row in what category the item falls.
Category =
IF (
startEnd[date] = STARTOFMONTH ( startEnd[date] )
|| startEnd[date] = ENDOFMONTH ( startEnd[date] );
"Category1";
"Category2"
)
table end result is:
Supose a student attandance system.
For a student and a course we have N:M relation named attandance.
Also whe have a model with attandances status (present, absent, justified, ...).
level( id, name, ... )
student ( id, name, ..., id_level )
course( id, name, ... )
status ( id, name, ...) #present, absemt, justified, ...
attandance( id, id_student, id_course, id_status, date, hour )
unique_together = ((id_student, id_course, id_status, date, hour),)
I'm looking for a list of students with >20% of absent for a level sorted by %. Something like:
present = status.objects.get( name = 'present')
justified = status.objects.get( name = 'justified')
absent = status.objects.get( name = 'absent')
#here the question. How to do this:
Student.objects.filter( level = level ).annotate(
nPresent =count( attandence where status is present or justified ),
nAbsent =count( attandence where status is absent ),
pct = nAbsent / (nAbsent + nPresent ),
).filter( pct__gte = 20 ).order_by( "-pct" )
If it is not possible to make it with query api, any workaround (lists, sets, dictionaris, ...) is wellcome!
thanks!
.
.
.
---- At this time I have a dirty raw sql writed by hand --------------------------
select
a.id_alumne,
coalesce ( count( p.id_control_assistencia ), 0 ) as p,
coalesce ( count( j.id_control_assistencia ), 0 ) as j,
coalesce ( count( f.id_control_assistencia ), 0 ) as f,
1.0 * coalesce ( count( f.id_control_assistencia ), 0 ) /
( coalesce ( count( p.id_control_assistencia ), 0 ) + coalesce ( count( f.id_control_assistencia ), 0 ) ) as tpc
from
alumne a
inner join
grup g
on (g.id_grup = a.id_grup )
inner join
curs c
on (c.id_curs = g.id_curs)
inner join
nivell n
on (n.id_nivell = c.id_nivell)
inner join
control_assistencia ca
on (ca.id_estat is not null and
ca.id_alumne = a.id_alumne )
inner join
impartir i
on ( i.id_impartir = ca.id_impartir )
left outer join
control_assistencia p
on (
p.id_estat in ( select id_estat from estat_control_assistencia where codi_estat in ('P','R' ) ) and
p.id_control_assistencia = ca.id_control_assistencia )
left outer join
control_assistencia j
on (
j.id_estat = ( select id_estat from estat_control_assistencia where codi_estat = 'J' ) and
j.id_control_assistencia = ca.id_control_assistencia )
left outer join
control_assistencia f
on (
f.id_estat = ( select id_estat from estat_control_assistencia where codi_estat = 'F' ) and
f.id_control_assistencia = ca.id_control_assistencia )
where
n.id_nivell = {0} and
i.dia_impartir >= '{1}' and
i.dia_impartir <= '{2}'
group by
a.id_alumne
having
1.0 * coalesce ( count( f.id_control_assistencia ), 0 ) /
( coalesce ( count( p.id_control_assistencia ), 0 ) + coalesce ( count( f.id_control_assistencia ), 0 ) )
> ( 1.0 * {3} / 100)
order by
1.0 * coalesce ( count( f.id_control_assistencia ), 0 ) /
( coalesce ( count( p.id_control_assistencia ), 0 ) + coalesce ( count( f.id_control_assistencia ), 0 ) )
desc
'''.format( nivell.pk, data_inici, data_fi, tpc )
If you don't care too much whether it uses the query api or python after the fact, use itertools.groupby.
attendances = Attendance.objects.select_related().filter(student__level__exact=level)
students = []
for s, g in groupby(attendances, key=lambda a: a.student.id):
g = list(g) # g is an iterator
present = len([a for a in g if a.status == 'present'])
absent = len([a for a in g if a.status == 'absent'])
justified = len([a for a in g if a.status == 'justified'])
total = len(g)
percent = int(absent / total)
students.append(dict(name=s.name, present=present, absent=absent, percent=percent))
students = (s for s in sorted(students, key=lambda x: x['percent']) if s['percent'] > 25)
You can pass the resulting list of dicts to the view the same way you would any other queryset.