datatables order by number doc and year of doc - datatables

I don't know how to implement a simple way to sort a column that show me number of doc with trailing year like:
COL 1 COL 2 COL 3 DOC. NR
------------------------------------
x x x 2/2020
------------------------------------
x x x 3/2020
------------------------------------
x x x 4/2021
------------------------------------
x x x 1/2022
------------------------------------
In my example i'd like to sort doc. nr col by asc or desc, based on number of doc (grouped by year).
I tried to set data-order with formula: numberdoc + year but it doesn't work cause, for example, 3 + 2020 is equal to 1 + 2022.... so this way is not correct. Any idea?
<td data-order="2020">1/2019</td>
Script:
$(document).ready( function () {
var table = $('#example').DataTable({
"aaSorting": [[ 1, "desc" ]],
"columnDefs": [
{
targets: [1],
data: {
_: "1.display",
sort: "1.#data-order",
type: "1.#data-order"
}
}
]
});
} );
My fiddle: http://live.datatables.net/jivekefo/1/edit
Expected (ASC) result:
1/2018
2/2018
3/2018
1/2019
2/2019
3/2019
4/2019
1/2020
...

Ok solved with this rule:
<td data-order="<?php echo (new Datetime($dateDoc))->format("Y") . str_pad(ltrim($numberDoc, "0"), 5, "0", STR_PAD_LEFT); /* example. 201900001 */ ?>">
http://live.datatables.net/jivekefo/2/edit

Related

How to update a pandas column

Given the following dataframe
col1 col2
1 ('A->B', 'B->C')
2 ('A->D', 'D->C', 'C->F')
3 ('A->K', 'K->M', 'M->P')
...
I want to convert this to the following format
col1 col2
1 'A-B-C'
2 'A-D-C-F'
3 'A-K-M-P'
...
Each sequence shows an arc within a path. Hence, the sequence is like (a,b), (b,c), (c,d) ...
def merge_values(val):
val = [x.split('->') for x in val]
out = []
for char in val:
out.append(char[0])
out.append(val[-1][1])
return '-'.join(out)
df['col2'] = df['col2'].apply(merge_values)
print(df)
Output:
col1 col2
0 1 A-B-C
1 2 A-D-C-F
2 3 A-K-M-P
Given
df = pd.DataFrame({
'col1': [1, 2, 3],
'col2': [
('A->B', 'B->C'),
('A->D', 'D->C', 'C->F'),
('A->K', 'K->M', 'M->P'),
],
})
You can do:
def combine(t, old_sep='->', new_sep='-'):
if not t: return ''
if type(t) == str: t = [t]
tokens = [x.partition(old_sep)[0] for x in t]
tokens += t[-1].partition(old_sep)[-1]
return new_sep.join(tokens)
df['col2'] = df['col2'].apply(combine)

Pandas | Filter DF rows with Integers that lie between two Integer values in another Dataframe

I got two Dataframes. The goal is to filter out rows in DF1 that have an Integer value that lies between any of the Integers in the ["Begin"] and ["End"] columns in any of the 37 rows in DF2.
DF1:
INDEX String IntValues
1 "string" 808091
2 "string" 1168262
3 "string" 1169294
... ... ...
647 "string" 14193661
648 "string" 14551918
DF2:
Index Begin End
1 1196482.2 1216529
2 1791819.7 1834887
3 2008405.1 2014344
... ... ...
36 14168540.0 14193933
37 14727507.1 14779605
I think it is possible to use something like :
df1[(df1["IntValues"] >=1196482.2 ) & (df1["IntValues"] <= 1216529),(... 36 more conditions)].
Is there a better way than just writing down these 37 conditions, like a variable for the begin and end values of that "filter window" ?
Edit: As requested a code sample, not from the original DF, but i hope it suffices.
d1 = {
"string":["String0", "String1", "String2", "String3", "String4", "String5", "String6", "String7", "String8", "String9", "String10", "String11", "String12", "String13", "String14"],
"timestamp":[1168262,1169294, 1184451, 1210449,1210543,1210607, 1644328,
1665732, 1694388,1817309,1822872,1825310,2093796,2182923,2209252 ],
"should be in": ["Yes", "Yes", "Yes", "No", "No","No", "yes","yes","yes","no","no", "no","yes","yes","no"]
}
df1 = pd.DataFrame(d1)
d2={
'begin' : [1196482.2,1791819.7,2199564.6],
'end' : [1216529,1834887,2212352]
}
df2 = pd.DataFrame(d2)
Try this:
df_final=[]
for i,j in zip(df2["Begin"],df2["End"]):
x=df1[(df1["IntValues"] >=i ) & (df1["IntValues"] <= j)]
df_final.append(x)
df_final=pd.concat(df_final,axis=0).reset_index(drop=True)
df_final=df_final.drop_duplicates()

Nested dictionary to pandas df

My first question in stackoverflow!
I have a triple nested dictionary and I want to convert it to pandas df.
The dictionary has the following structure:
dictionary = {'CompanyA': {'Revenue': {date1 : $1}, {date2: $2}},...
{'ProfitLoss': {date1 : $0}, {date2: $1}}},
'CompanyB': {'Revenue': {date1 : $1}, {date2: $2}},...
{'ProfitLoss': {date1 : $0}, {date2: $1}}},
'CompanyC': {'Revenue': {date1 : $1}, {date2: $2}},...
{'ProfitLoss': {date1 : $0}, {date2: $1}}}}
So far I been able to construct a df using:
df = pd.DataFrame.from_dict(dictionary)
But the results its a df with values as dictionaries like this:
CompanyA CompanyB CompanyC
Revenue {date1:$0,..} {date1:$1,..} {date1:$0,..}
ProfitLoss{date1:$0,..} {date1:$0,..} {date1:$0,..}
I want the table to look like this:
CompanyA CompanyB CompanyC
Revenue Date1 $1 $1 $1
Date2 $2 $2 $2
ProfitLoss Date1 $0 $0 $0
Date2 $1 $1 $1
I had tried using pd.MultiIndex.from_dict (.from_product) and change the index, with no result. Any idea what to do next? Any hint will be appreciated!
I see you're new, but there may be an answer to a similar question, see this. Next time try looking for a similar question using keywords. For example, I found the one I linked by searching "pandas nested dict", and that's it, the first link was the SO post!
Anyway, you need to reshape your input dict. You want a dict structured like this:
{
'CompanyA': {
('Revenue', 'date1'): 1,
('ProfitLoss', 'date1'): 0,
}
...
}
I would do something like this:
import pandas as pd
data = {
'CompanyA': {
'Revenue': {
"date1": 1,
"date2": 2
},
'ProfitLoss': {
"date1": 0,
"date2": 1
}
},
'CompanyB': {
'Revenue': {
"date1": 4,
"date2": 5
},
'ProfitLoss': {
"date1": 2,
"date2": 3
}
}
}
# Reshape your data and pass it to `DataFrame.from_dict`
df = pd.DataFrame.from_dict({i: {(j, k): data[i][j][k]
for j in data[i] for k in data[i][j]}
for i in data}, orient="columns")
print(df)
Output:
CompanyA CompanyB
ProfitLoss date1 0 2
date2 1 3
Revenue date1 1 4
date2 2 5
EDIT
Using actual datetimes to respond to your comment:
import pandas as pd
import datetime as dt
date1 = dt.datetime.now()
date2 = date1 + dt.timedelta(days=365)
data = {
'CompanyA': {
'Revenue': {
date1: 1,
date2: 2
},
'ProfitLoss': {
date1: 0,
date2: 1
}
},
'CompanyB': {
'Revenue': {
date1: 4,
date2: 5
},
'ProfitLoss': {
date1: 2,
date2: 3
}
}
}
# Reshape your data and pass it to `DataFrame.from_dict`
df = pd.DataFrame.from_dict({i: {(j, k): data[i][j][k]
for j in data[i] for k in data[i][j]}
for i in data}, orient="columns")
print(df)
Output:
CompanyA CompanyB
ProfitLoss 2018-10-08 11:19:09.006375 0 2
2019-10-08 11:19:09.006375 1 3
Revenue 2018-10-08 11:19:09.006375 1 4
2019-10-08 11:19:09.006375 2 5

Maximum in List of Records

Say I have a List of records in elm:
[ { id = 1, magnitude = 100 }
, { id = 3, magnitude = 300 }
, { id = 2, magnitude = 200 } ]
and I want to get the record with the greatest magnitude value (300). What is a good way of doing this?
The docs gives an example of using the "maximum" -method, but it uses a simple list of integers. How is it done with records?
Update based on recommendation from #robertjlooby
There is a function called maximumBy which does exactly this in elm-community/list-extra. Example:
List.Extra.maximumBy .magnitude list
Original Answer
There are a few ways to achieve this.
This first way is more concise but it involves sorting the whole list, reversing it, then taking the head.
maxOfField : (a -> comparable) -> List a -> Maybe a
maxOfField field =
List.head << List.reverse << List.sortBy field
If you want something that's more efficient and only traverses the list once, here's a more efficient version:
maxOfField : (a -> comparable) -> List a -> Maybe a
maxOfField field =
let f x acc =
case acc of
Nothing -> Just x
Just y -> if field x > field y then Just x else Just y
in List.foldr f Nothing
An example of it in use:
list =
[ { id = 1, magnitude = 100 }
, { id = 3, magnitude = 300 }
, { id = 2, magnitude = 200 } ]
main =
text <| toString <| maxOfField .magnitude list
Here is a version that uses foldl and a default record:
bigger =
let
choose x y =
if x.magnitude > y.magnitude then
x
else
y
in
List.foldl choose {id = 0, magnitude = 0} items
Sebastian's answer add an arbitrary start value which could cause a problem if all your magnitudes were negative. I would adjust to
bigger items =
case items of
[] -> []
(h :: []) -> h
(h :: tail) ->
let
choose x y =
if x.magnitude > y.magnitude then
x
else
y
in
List.foldl choose h tail

How do I refer to variable in func argument when same is used in foreach

How can I refer to date as argument in f within the foreach loop if date is also used as block element var ? Am I obliged to rename my date var ?
f: func[data [block!] date [date!]][
foreach [date o h l c v] data [
]
]
A: simple, compose is your best friend.
f: func[data [block!] date [date!]][
foreach [date str] data compose [
print (date)
print date
]
]
>> f [2010-09-01 "first of sept" 2010-10-01 "first of october"] now
7-Sep-2010/21:19:05-4:00
1-Sep-2010
7-Sep-2010/21:19:05-4:00
1-Oct-2010
You need to either change the parameter name from date or assign it to a local variable.
You can access the date argument inside the foreach loop by binding the 'date word from the function specification to the data argument:
>> f: func[data [block!] date [date!]][
[ foreach [date o h l c v] data [
[ print last reduce bind find first :f 'date 'data
[ print date
[ ]
[ ]
>> f [1-1-10 1 2 3 4 5 2-1-10 1 2 3 4 5] 8-9-10
8-Sep-2010
1-Jan-2010
8-Sep-2010
2-Jan-2010
It makes the code very difficult to read though. I think it would be better to assign the date argument to a local variable inside the function as Graham suggested.
>> f: func [data [block!] date [date!] /local the-date ][
[ the-date: :date
[ foreach [date o h l c v] data [
[ print the-date
[ print date
[ ]
[ ]
>> f [1-1-10 1 2 3 4 5 2-1-10 1 2 3 4 5] 8-9-10
8-Sep-2010
1-Jan-2010
8-Sep-2010
2-Jan-2010