I have a list of tables (in actual data) with different columns for which, after to combine, I get a table of 15 columns. In actual data, the list of tables is get from several previous steps and each step takes less than a second, but only Table.Combine() takes almost 2 minutes with an input of about 1200 rows. In order to show the example, I show below an output of 4 columns only,
Is there a faster alternative way to get the same output given by Table.Combine()? Thanks for any help.
This is the code of the query I has so far.
let
Tables = {
Table.FromRecords({[Name = "Bob", Phone = "123-4567"],
[Name = "",Phone = ""]
}),
Table.FromRecords({[Fax = "987-6543", Phone = "838-7171"],
[Fax = "", Phone = "233-687"],
[Fax = "", Phone = "544-778"]
}),
Table.FromRecords({[Cell = "543-7890"],
[Cell = ""],
[Cell = ""]
})
},
CombinedTable = Table.Combine(Tables)
in
CombinedTable
The current output is:
UPDATE
This is the entire query, with Table.Buffer() added in step group5
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("jVNdb4JAEPwvPFty3KHUR1C4Sg+0x5lqqSF+tGlqH5q0mv787hkal41FEsLNLjczu5NQlk6kpqP7yixnceU5Pad+Vr3SCQF4qI4A9FE9AiBQXcyj6qTWlBkDYKiOSd1C8wkNTyPpdK174DntHpzscUucB8R5iOqE6rU6B1ecOXEeEueOUXmE5nejBS1uCZHt6C5JnCge3mReiiMLJ/mNELidARgZreMCNTWAsQozPMgC0N2DFbHK8unUTTOr9XxgTGzzuVIn9AKtRZrDe7M5uod3xrj7uf8I2MD9Or7u1t9rxA2VmsJRGIPui//vX/CK8rOX7zHLFXBgbntM9L+T01koSUaRnvQNiciEanw1Ir37gSLZ7mx/Uw/qcbFvDKjjFD7Bijq1Eywf64uC87egWwzS/xP3hmfG6hc=", BinaryEncoding.Base64), Compression.Deflate)),
let
_t = ((type nullable text) meta [Serialized.Text = true])
in
type table [COL1 = _t, COL2 = _t, COL3 = _t, COL4 = _t]
),
fx = each not List.IsEmpty(List.RemoveItems(_,{"",null})),
group0 = Table.Group(Source, "COL2", {"n", each _}, 0, (x, y) => Byte.From(y = "" or y = null)),
group1 = Table.TransformColumns(
group0,
{
"n",
each
let
a = Table.Skip(_),
b = Table.FirstN(a, each [COL3] = "" or [COL3] = null),
c = Table.Skip(a, Table.RowCount(b))
in
[a = a, b = b, c = c]
}
),
group2 = Table.TransformColumns(
group1,
{"n", each Table.ToColumns(Table.Transpose([b])) & Table.ToColumns([c])}
),
group3 = Table.TransformColumns(group2, {"n", each List.Select(_, fx)}),
group4 = Table.TransformColumns(group3, {"n", each Table.FromColumns(_)}),
group5 = Table.Buffer( Table.TransformColumns(group4, {"n", each Table.PromoteHeaders(_)}) ) ,
combine = Table.Combine(group5[n]),
Custom1 = Table.SelectRows(combine, each fx(Record.ToList(_)))
in
Custom1
The purpose of this query is to tabulate data that appears in repeated blocks and subblock in the way I show below.
This is the output given by the query.
No, but try wrapping the initial table definitions as you go along in Table.Buffer()
let
a= Table.Buffer(Table.FromRecords({[Name = "Bob", Phone = "123-4567"],[Name = "",Phone = ""]})),
b= Table.Buffer(Table.FromRecords({[Fax = "987-6543", Phone = "838-7171"], [Fax = "", Phone = "233-687"],[Fax = "", Phone = "544-778"]})),
c= Table.Buffer(Table.FromRecords({[Cell = "543-7890"],[Cell = ""],[Cell = ""]})),
CombinedTable = Table.Combine({a,b,c})
in CombinedTable
Related
I have the code below that
Searches the concatenation of the numeric parts in column STR of table Source within column VAL2 of table Codes. For example, for string abc.sec712.fir001.wpqdata, looks for 712001 in column VAL2. (CustomOUT1)
Searches the best match for values in column NUM of table Source within column VAL1 of table Codes. (Step `CustomOUT2)
These two steps are done separated using Table.AddColumn() in step CustomOUT1 and CustomOUT2.
Since both steps are using Table.AddColumn(), I'd like to join the logic of both steps in a single Table.AddColumn() step.
How can I do this?
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("ZY3LCsIwEEX/JesSMsl0kiwFobZqK4WsQhexVXDnC/x9UyVqEAbu5XCY6z1bbGtWMCBCjMmGwrO+72JVwmqjbIKNa2cokQx8YLVysSJaW2qT4LrbxErKAonEdq+X8cJ+5LfDqEHy4+kqBPDH+TKFe/hZ/mqqpFkDEJlWt1Wu4VvDXFs2LtOk+B8dng==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [TRS = _t, NUM = _t, STR = _t]),
Codes = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("XZDNjoMwDITfhXMPdn4cfOymqEUNzQqCWhX1/V9jbbPsYU8gT+absbetq6W0oXanLjKmJN/kCcB3n9PWLfM8LYvMOLmY0MlfcBEgmTrnXK+zzDwQq9OBA0DTxvM5P0eZoaPgfNRXFPsABzc/lYtEIbByfQw97eo85jkrNwJ5APVK9kFelGzemCAhqRelABydct07/a80lHKvg0ouUI8sDtVJXphepykXPQT2jplRXyYAcKbmda0t25k8s3UKIu7WYV0vqOjgKREIQNH0F/0ehq/81jtyiFFzzbuTH7LP/WG5xERgxyDE34Vaa5MtFJHJsD0Amba+Xt9tNU321MJOC++Zt1Ku7SYz8oxkVaU8Rov9/AA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [CODE = _t, VAL1 = _t, VAL2 = _t]),
CustomOUT1
= Table.AddColumn(
Source,
"OUT1",
(i) =>
try
Table.SelectRows(
Codes,
each Text.Middle(i[STR],7,3) & Text.Middle(i[STR],14,3) = [VAL2]
)[CODE]{0}
otherwise
"NOT FOUND"
,type text ),
CustomOUT2 = Table.AddColumn(
CustomOUT1,
"OUT2",
each
if [NUM] = "" then
null
else
let
t = Table.AddIndexColumn(
Table.SelectRows(
Codes,
(x) =>
let
s = List.Sort({x[VAL1], [NUM]}, each Text.Length(_))
in
Text.StartsWith(s{1}, s{0})
),
"Index"
)
in
if Table.RowCount(t) > 0 then
Table.First(
Table.Sort(
t,
(y) =>
Number.BitwiseShiftLeft(
Number.Abs(Text.Length([NUM]) - Text.Length(y[VAL1])),
32
)
+ y[Index]
)
)[CODE]
else
"NOT FOUND"
,type text)
in
CustomOUT2
Tables Source and Codes
Table with both outputs from two AddColumn Steps
Desired output
Easiest?
....
CustomOUT2 = Table.AddColumn(
CustomOUT1,
"OUT",
each
if [NUM] = "" then
[OUT1]
...
then right click and remove column OUT1
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("ZY3LCsIwEEX/JesSMsl0kiwFobZqK4WsQhexVXDnC/x9UyVqEAbu5XCY6z1bbGtWMCBCjMmGwrO+72JVwmqjbIKNa2cokQx8YLVysSJaW2qT4LrbxErKAonEdq+X8cJ+5LfDqEHy4+kqBPDH+TKFe/hZ/mqqpFkDEJlWt1Wu4VvDXFs2LtOk+B8dng==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [TRS = _t, NUM = _t, STR = _t]),
Codes = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("XZDNjoMwDITfhXMPdn4cfOymqEUNzQqCWhX1/V9jbbPsYU8gT+absbetq6W0oXanLjKmJN/kCcB3n9PWLfM8LYvMOLmY0MlfcBEgmTrnXK+zzDwQq9OBA0DTxvM5P0eZoaPgfNRXFPsABzc/lYtEIbByfQw97eo85jkrNwJ5APVK9kFelGzemCAhqRelABydct07/a80lHKvg0ouUI8sDtVJXphepykXPQT2jplRXyYAcKbmda0t25k8s3UKIu7WYV0vqOjgKREIQNH0F/0ehq/81jtyiFFzzbuTH7LP/WG5xERgxyDE34Vaa5MtFJHJsD0Amba+Xt9tNU321MJOC++Zt1Ku7SYz8oxkVaU8Rov9/AA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [CODE = _t, VAL1 = _t, VAL2 = _t]),
CustomOUT1
= Table.AddColumn(
Source,
"OUT1",
(i) =>
try
Table.SelectRows(
Codes,
each Text.Middle(i[STR],7,3) & Text.Middle(i[STR],14,3) = [VAL2]
)[CODE]{0}
otherwise
"NOT FOUND"
,type text ),
CustomOUT2 = Table.AddColumn(
CustomOUT1,
"OUT",
each
if [NUM] = "" then
[OUT1]
else
let
t = Table.AddIndexColumn(
Table.SelectRows(
Codes,
(x) =>
let
s = List.Sort({x[VAL1], [NUM]}, each Text.Length(_))
in
Text.StartsWith(s{1}, s{0})
),
"Index"
)
in
if Table.RowCount(t) > 0 then
Table.First(
Table.Sort(
t,
(y) =>
Number.BitwiseShiftLeft(
Number.Abs(Text.Length([NUM]) - Text.Length(y[VAL1])),
32
)
+ y[Index]
)
)[CODE]
else
"NOT FOUND"
,type text),
#"Removed Columns" = Table.RemoveColumns(CustomOUT2,{"OUT1"})
in #"Removed Columns"
sorry if this is repetitive and so simple it is annoying, but I am new to Shiny.
I need help with a shiny app I am trying to create for my golf game. I have loaded a CSV file with previous distance and accuracy observations to Rstudio and completed a script file with what will generally be done: data preprocessing and then visualizations.
I am now struggling with converting that to the app.R file, specifically, how to create a widget where I can add new numeric observations to the current data frame. The end goal is to use the app to log data as I play (practice or an actual round), which updates in real time for quick insight into the average distance and accuracy for each club.
Here is the very basic shiny code I have got to work for the numeric input:
`library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
titlePanel("Numeric Add Test"),
column(3,
numericInput("num",
h3("Numeric input"),
value = 1,
min = 50,
max = 400,
step = 25))
)
# Define server logic required to draw a histogram
server <- function(input, output) {
}
# Run the application
shinyApp(ui = ui, server = server)`
I have found ways to include an 'add' button to a list, but what I am hoping to do is have the new numeric input be added to the specified variable (club, distance, accuracy) in the referenced dataset. This action would change the existing data, but add to it and grow the dataset over time.
Not sure if this helps for context at all, but below is the script file for preprocessing and visuals I described above:
`######### Golf Data Practice for App #############
## Read in Data set and address the column names starting with a number
Golfdata <- data.frame(read_csv("Shiny Apps/Golf Dataset .csv"))
Golfdata <- as.data.frame(Golfdata)
#Drop the last two columns for only clubs. Then create shot bias DF as well.
Clubs <- Golfdata %>% select(-c(11,12))
ShotBias <- Golfdata %>% select(c(11,12))
#Visualize the Average club distance
##Convert the club df by summarizing each variable by its average,
## then use the gather() to convert to long instead of wide to finally
## prepare the df for visualizing.
ClubAverage <- Clubs %>% summarise_all(mean) %>% gather(ClubAverage) %>%
mutate_if(is.numeric, round, digits = 0)
library(ggplot2)
value <- ClubAverage$value
ggplot(ClubAverage) +
aes(x = fct_reorder(ClubAverage, value, .desc = TRUE), y = value, label = value,
color = ClubAverage) +
geom_col( show.legend = FALSE, fill = "white") +
geom_text(nudge_y = 10, color = "black", size=4, fontface = "bold") +
labs(x = "Club",
y = "Yards", title = "Average Club Distance") +
theme(panel.background = element_rect(fill="forestgreen"),
panel.grid.major.x = element_blank(),
panel.grid.major = element_line(color = "yellow"),
panel.grid.minor = element_line(color = "yellow1")) +
theme(plot.title = element_text(size = 24L,
face = "bold", hjust = 0.5), axis.title.y = element_text(size = 18L, face = "bold"), axis.title.x =
element_text(size = 18L,
face = "bold"))
## Visualize the Average Accuracy ##
## This time, summarize the columns by their mean,
## but keep as wide -- no gather() function needed.
AverageShotBias <- ShotBias %>% summarise_all(mean)
ggplot(AverageShotBias) +
aes(x = Accuracy.Bias, y = Distance.Bias) +
geom_point(shape = "circle filled",
size = 18L, fill = "yellow") +
labs(x = "Accuracy", y = "Distance", title = "Average Shot Bias") +
theme(panel.background = element_rect(fill="forestgreen")) +
theme(plot.title = element_text(size = 24L, face = "bold", hjust = 0.5), axis.title.y =
element_text(size = 14L,
face = "bold"), axis.title.x = element_text(size = 14L, face = "bold")) +
xlim(-1, 1) +
ylim(-1, 1) +
geom_hline(yintercept = 0, size=1) +
geom_vline(xintercept = 0, size=1)`
Something I have found regarding the add button is the code here:
` ,actionButton('add','add')
,verbatimTextOutput('list')
)`
This does create an add button, which after updating the server code does create a list of added inputs, however I would like to be able to adjust the code for adding the observation to the variables in the data set.
I assume I would create an add button for each variable, just need to understand better how to do that.
The structure of your data used in the plot is not clear, but this is how to get the inputs or update dataset using eventReactive or observeEvent in the server. you can read this to learn the difference
server <- function(input, output) {
distance <- eventReactive(input$addButton, {
input$distInput
}, ignoreInit = T, ignoreNULL = F)
accbias <- eventReactive(input$accBiasButton, {
input$accslider
})
distbias <- eventReactive(input$DistBiasButton, {
input$distslider
}, ignoreNULL=F)
output$plot1 <- renderPlot({
input$distInput
mydist <- distance()
# plot
})
output$plot2 <- renderPlot({
input$distInput # use the inputs here
mydist <- distance() # or the reactives
})
}
the two output plots in your code have the same outputId
Follow UP to my Question: I have written the code for the ui, now I am still trying to figure out how to code the server properly so the distance and accuracy numeric inputs can be added to a data frame. That data frame will then be used to create the two visuals.
library(shiny)
library(gridlayout)
library(DT)
library(tidyverse)
ui <- grid_page(
layout = c(
"title title title",
"h1 h2 h3 ",
"h4 h4 h5 "
),
row_sizes = c(
"100px",
"0.86fr",
"1.14fr"
),
col_sizes = c(
"250px",
"0.71fr",
"1.29fr"
),
gap_size = "1rem",
grid_card_text(
area = "title",
content = "My Golf Data",
alignment = "center",
is_title = FALSE
),
grid_card(
area = "h2",
title = "Distance Input",
numericInput(
inputId = "distInput",
label = "Distance",
value = 50L,
min = 50L,
max = 400L,
step = 15L
),
actionButton(
inputId = "addButton",
label = "Add",
width = "100%"
)
),
grid_card(
area = "h1",
title = "Club Select",
radioButtons(
inputId = "clubRadiobuttons",
label = "",
choices = list(
Driver = "D",
`5Wood` = "5W",
`4H` = "4H",
`5I` = "5I",
`6I` = "6I",
`7I` = "7I",
`8I` = "8I",
`9I` = "9I",
PW = "PW",
SW = "SW"
),
width = "100%"
)
),
grid_card(
area = "h3",
title = "Accuracy",
sliderInput(
inputId = "accslider",
label = "Accuracy Bias",
min = -1L,
max = 1L,
value = 0L,
width = "98%",
step = 1L
),
actionButton(
inputId = "accBiasButton",
label = "Add Acc Bias",
width = "100%"
),
sliderInput(
inputId = "distslider",
label = "Distance Bias",
min = -1L,
max = 1L,
value = 0L,
width = "100%",
step = 1L
),
actionButton(
inputId = "DistBiasButton",
label = "Add Dist Bias",
width = "100%"
)
),
grid_card(
area = "h5",
title = "Average Club Distance",
plotOutput(
outputId = "plot",
width = "100%",
height = "400px"
)
),
grid_card(
area = "h4",
title = "Accuracy Average",
plotOutput(
outputId = "plot",
width = "100%",
height = "400px"
)
)
)
server <- function(input, output) {
}
shinyApp(ui, server)
I have a project that needs me to remove items if one of the properties of the item I'm trying to find within the list is true. Just so it's easier understand the project I am pasting all code needed to understand it below.
fun main() {
val acct1 = AccountId(72)
val calendars = mutableListOf<CalendarDrawerCalendarItem>()
val calendars2 = mutableListOf<CalendarDrawerCalendarItem>()
calendars.add(CalendarDrawerCalendarItem(CalendarDescriptor(acct1, CalendarId(acct1, 3),"toast", true)))
calendars.add(CalendarDrawerCalendarItem(CalendarDescriptor(acct1, CalendarId(acct1, 4), "chicken", false)))
calendars.add(CalendarDrawerCalendarItem(CalendarDescriptor(acct1, CalendarId(acct1, 5), "pizza", true)))
calendars2.add(CalendarDrawerCalendarItem(CalendarDescriptor(acct1, CalendarId(acct1, 1), "bagel", true)))
// These are example calls to collapse
collapse(calendars, CalendarDrawerGroupItem(true, CalendarGroupDescriptor( acct1, "My Calendars")))
collapse(calendars2, CalendarDrawerGroupItem(false, CalendarGroupDescriptor(acct1, "Group Calendars")))
}
fun collapse(calendars: List<CalendarDrawerListItem>, group: CalendarDrawerGroupItem): List<CalendarDrawerListItem> {
val collapsedResults = mutableListOf<CalendarDrawerListItem>()
val findGroupGiven = group
collapsedResults.addAll(calendars)
if (collapsedResults.contains(findGroupGiven)) {
group.collapsed = true
// logic for deleting items here
}
return collapsedResults
}
I'll also put the classes so you can see how they're defined
data class AccountId(
val accountId: Int
)
data class CalendarId(
val accountId: AccountId,
val calendarId: Int)
data class CalendarDescriptor(
val accountId: AccountId,
val calendarId: CalendarId,
val name: String,
val isGroupCalendar: Boolean
)
data class CalendarGroupDescriptor(
val accountId: AccountId,
val name: String,
)
sealed class CalendarDrawerListItem
data class CalendarDrawerGroupItem(var collapsed: Boolean, val groupDescriptor: CalendarGroupDescriptor) : CalendarDrawerListItem()
data class CalendarDrawerCalendarItem(val calendarDescriptor: CalendarDescriptor) : CalendarDrawerListItem()
The first step I have done is I must find the given group from the group variable, within calendars. (I did this with the contains() method). Next when I find the group I have to set its collapsed variable to true and any CalendarDrawerCalendarItems after it have to be deleted.
The input will look something like (the exact numbers and values are not the important part):
Input:
calendars:
CDGroupItem(collapsed = false, groupDescriptor = GroupDescriptor(accountId = 1, name = "My calendars"))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 1, isGroup = false))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 2, isGroup = false))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 3, isGroup = false))
CDGroupItem(collapsed = false, groupDescriptor = GroupDescriptor(accountId = 1, name = "Group calendars"))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 4, isGroup = true))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 5, isGroup = true))
group: CDGroupItem(collapsed = false, groupDescriptor = GroupDescriptor(accountId = 1, name = "My calendars"))
The output should look something like this:
Output:
CDGroupItem(collapsed = true, groupDescriptor = GroupDescriptor(accountId = 1, name = "My calendars"))
CDGroupItem(collapsed = false, groupDescriptor = GroupDescriptor(accountId = 1, name = "Group calendars"))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 4, isGroup = true))
CDCalendarItem(calendarDescriptor = CalendarDescriptor(accountId = 1, calendarId = 5, isGroup = true))
Any group item that has its collapsed boolean set to true should have all calendar items deleted after it since its collapsed is set to true. Again the names and numbers are not super important. The collapsed bool is. How can I do this without hardcoding or using indicies?
Your example code doesn't use that input and output as-is so I can only give you a general example, but you could use a fold:
val result = calendars.fold(mutableListOf<CalendarDrawerListItem>()) { items, current ->
// basically 'is there a last item stored, and is it a group item, and is it collapsed'
val lastStoredIsCollapsed =
(items.lastOrNull() as? CalendarDrawerGroupItem)?.collapsed == true
if (current is CalendarDrawerCalendarItem && lastStoredIsCollapsed) items
else items.apply { add(current) }
}
It basically pipes out each item into a list, but if the last one it stored is a CalendarDrawerGroupItem with collapsed set to true, it drops drawer items. If the last one is a non-collapsed group item, it can store a drawer item, and that means the next drawer item will be stored (since the last item isn't a collapsed group)
edit: here's the for loop equivalent if it helps, with the full logic for when a calendar is not dropped (the logic in my other example is for whether it should be dropped, which can be condensed a bit):
// assuming 'calendars' is your list of items with 'collapsed' set appropriately
val result = mutableListOf<CalendarDrawerListItem)
for (calendar in calendars) {
val lastStored = result.lastOrNull()
when {
lastStored == null ->
result.add(calendar)
lastStored is CalendarDrawerGroupItem && !lastStored.collapsed ->
result.add(calendar)
lastStored is CalendarDrawerCalendarItem ->
result.add(calendar)
}
}
return result
If you're asking how to actually mutate your list so a collapsed property is set to true, that would be easy if the property was a var in your data class. Since it's a val you'll have to do something like this:
val calendarInputWithCollapsedSet = calendars.map { calendar ->
if ((calendar as? CalendarDrawerGroupItem)?.groupDescriptor == group.groupDescriptor)
calendar.copy(collapsed = true) else calendar
}
So if you find a matching group (you'll have to work out how to match them, I'm guessing) you transform it into a copy with its collapsed property set
And then you can run the fold or whatever on that new list.
I am trying to format a table in shiny using DT::datatable. All my tables can have the default container but only when I pass the container argument that is when I want it to be designed as passed. I have tried multiple options of using if conditions but to no avail. WHen I looked at the datatable code, it says that if the container function is missing it takes a default type. I tried to coerce the same as well but it is still giving me an error.
Please help on this. Below is the code for the same:
table_opt = function(x, edit_y, container_dat = NULL, form_type = "", col_list = NULL){
DT::renderDataTable({
####### Percentage Format
if(form_type == "%")
{
datatable(x
,editable = edit_y
,if(is.null(container_dat)){container = expr()} else {container = container_dat}
,rownames = F
,options = list(
paging = F
,ordering = F
,searching = F
,deferRender = T
,class = "compact"
,headerCallback = JS(
"function(thead) {",
"$(thead).css('font-size','14px');",
"$(thead).css('background-color','#000000');",
"$(thead).css('color','#ffffff');",
"}"
,columnDefs = list(list(className = 'dt-center', targets = '_all'))
)) %>%
formatPercentage(col_list,digits = 2)
}
})
}
do.call should accomplish what you're trying to do.
table_opt = function(x, edit_y, container_dat = NULL, form_type = "", col_list = NULL){
DT::renderDataTable({
####### Percentage Format
if(form_type == "%")
{
dt_args <- list(data = x
,editable = edit_y
,rownames = F
,options = list(
paging = F
,ordering = F
,searching = F
,deferRender = T
,class = "compact"
,headerCallback = JS(
"function(thead) {",
"$(thead).css('font-size','14px');",
"$(thead).css('background-color','#000000');",
"$(thead).css('color','#ffffff');",
"}"
,columnDefs = list(list(className = 'dt-center', targets = '_all'))
))
)
if(!is.null(container_dat)) dt_args$container <- container_dat
do.call("datatable", dt_args) %>%
formatPercentage(col_list,digits = 2)
}
})
}
Using the Northwind database from RavenDB tutorial I'm trying to group orders by employee and get the most resent order for every employee.
Map:
from order in docs.Orders
select new {
Employee = order.Employee,
Count = 1,
MostRecent = order.OrderedAt,
MostRecentOrderId = order.Id
}
Reduce with nonexisting MaxBy:
from result in results
group result by result.Employee into grp
select new {
Employee = grp.Key,
Count = grp.Sum(result => result.Count),
MostRecent = grp.Max(result => result.MostRecent),
MostRecentOrderId = grp.MaxBy(result => result.MostRecent).MostRecentOrderId,
}
Reduce attempt:
from result in results
group result by result.Employee into grp
let TempMostRecent = grp.Max(result => result.MostRecent)
select new {
Employee = grp.Key,
Count = grp.Sum(result => result.Count),
MostRecent = TempMostRecent,
MostRecentOrderId = grp.First(result => result.MostRecent == TempMostRecent).MostRecentOrderId
}
However my reduce attempt returns 0 results.
Also: will RavenDB treat the Order.OrderetAt as a proper DateTime value and order them correctly?
You need to do it like
from order in docs.Orders
select new {
Employee = order.Employee,
Count = 1,
MostRecent = order.OrderedAt,
MostRecentOrderId = order.Id
}
from result in results
group result by result.Employee into grp
let maxOrder = grp.OrderByDescending(x=>x.MostRecent).First()
select new {
Employee = grp.Key,
Count = grp.Sum(result => result.Count),
MostRecent = maxOrder.MostRecent,
MostRecentOrderId = maxOrder.MostRecentOrderId,
}