Wie erwähnt in unserem Blogbeitrag über OData-Unterstützung in Mendix, OData ist auch nützlich, wenn Sie in Ihren Anwendungen auf Daten zugreifen möchten von R or RStudio. In diesem Blogbeitrag zeige ich Ihnen, wie das geht. Außerdem gebe ich einige einfache Beispiele für die Verwendung von R für Personen, die damit nicht vertraut sind.
Was ist R?
R ist eine sehr beliebte Open-Source-Programmiersprache für statistische Analysen, die von vielen Datenwissenschaftlern verwendet wird. Sie können eine kostenlose Open-Source-Version herunterladen, aber Sie finden R-Unterstützung auch in vielen kommerziellen Tools, darunter Microsoft Revolution R, Tibco Spitfire, Pivotal, Oracle und Tableau. Das Interessante an R ist, dass es eine große Anzahl von Bibliotheken gibt, die Sie verwenden können. Die Bibliotheken reichen von Datenmanipulationsalgorithmen über Diagramme und Berichte bis hin zu maschinellem Lernen.
Laden von OData in R
Um OData in R abzurufen, verwenden wir zwei Pakete: httr , XML. Das erste Paket ermöglicht das Lesen von Daten aus dem Web, das zweite kann zum Parsen von XML-Dokumenten verwendet werden.
Mit einer kleinen Funktion, die diese Pakete verwendet, können Sie eine OData-Ressource abrufen und in R-Daten umwandeln.
dataset <- getODataResource(<url of the odata resource>,<username>,<password>)
Bevor wir beginnen, müssen wir die benötigten Bibliotheken angeben.
library('httr')
library('XML')
library('dplyr')
library('lubridate')
Die Funktion getODataResource liest zuerst die OData-Ressource und analysiert das zurückgegebene XML-Dokument mithilfe des Httr-Pakets. Anschließend ermittelt sie die Namen der Attribute, ruft die Werte ab und erstellt einen Datenrahmen, der die Werte enthält.
getODataResource <- function(resourcePath,domain,usr,pwd){
url <- paste(domain, resourcePath,sep="")
# get the OData resource
response <- GET(url,authenticate(usr,pwd))
# parse xml docucument
responseContent <- content(response,type="text/xml")
# determine the names of the attributes
xmlNames <- xpathSApply(responseContent,
'//ns:entry[1]//m:properties[1]/d:*',xmlName,
namespaces = c(ns = "https://www.w3.org/2005/Atom",
m="https://schemas.microsoft.com/ado/2007/08/dataservices/metadata",
d="https://schemas.microsoft.com/ado/2007/08/dataservices"))
# determine all attribute values
properties <- xpathSApply(responseContent,'//m:properties/d:*',xmlValue)
# cast the attributes values into a data frame
propertiesDF <-
as.data.frame(matrix(properties,ncol=length(xmlNames),byrow=TRUE))
# set the column names
names(propertiesDF) <- xmlNames
return(propertiesDF)
}
Dies ist die grundlegende Funktionalität, die Sie abrufen müssen Mendix OData-Ressourcen in R. In seiner aktuellen Form verarbeitet es keine verschachtelten Daten, also beispielsweise Bestellungen mit in den Bestellungen verschachtelten Bestellpositionen. Es verwendet auch nicht die Datentypinformationen, die in der OData-Ressource enthalten sind. Stattdessen verwenden wir einige R-Ausdrücke, um die Datentypen manuell anzugeben, wie unten dargestellt.
Beispielanwendungsfall
Das Beispiel Mendix Die Anwendung verfügt über Ressourcen für Bestellungen, Kunden und Adressen. Wir erstellen eine Übersicht über die Anzahl der Bestellungen pro Stadt in R.
Zunächst definieren wir, wie wir eine Verbindung zu den OData-Ressourcen in unserem Mendix Anwendung.
domain <- "https://localhost:8080/"
username <- "demo_reporter"
password <- "goSfcsDj00"[/bash]
The following will load all the objects in the customers and address entities into R data frames.
[bash]customers <- getODataResource("odata/Orders/Customers()",domain,username,password)
addresses <- getODataResource("odata/Orders/Address()",domain,username,password)
Bei Bestellungen sind wir nur an den Bestellungen interessiert, die seit dem 1. Januar 2014 erstellt wurden. Wir könnten in R nach Bestelldatum filtern, aber wenn wir es in der OData-Ressourcen-URL angeben, vermeiden wir den Aufwand, sie von Ihrem Mendix Datenbank und den Transport aller Daten aus der Mendix Laufzeit zu R.
orders <- getODataResource(
"odata/Orders/Orders()/?$filter=OrderDate%20gt%20datetimeoffset'2014-01-01T00:00:00z'"
,domain,username,password)
Die Datenrahmen enthalten alle Mendix Objekte, die über OData-Ressourcen abgerufen werden. Die ersten fünf Auftragsdatensätze sehen folgendermaßen aus:
orders[1:5,c("OrderNumber","Order_Customer","OrderDate")]
## OrderNumber Order_Customer OrderDate
## 1 1 2533274790395905 2015-01-18T10:32:00.000Z
## 2 2 2533274790395906 2014-01-30T07:01:00.000Z
## 3 3 2533274790395907 2014-04-16T13:15:00.000Z
## 4 4 2533274790395908 2014-09-19T07:52:00.000Z
## 5 5 2533274790395909 2015-01-14T07:28:00.000Z
Da wir nun die Daten haben, müssen wir sicherstellen, dass wir die richtigen Datentypen verwenden. Mendix IDs werden mit Longs implementiert in Mendix. In R können Sie Doubles verwenden.
customers$DateOfBirth <- ymd_hms(customers$DateOfBirth)
customers$ID <- as.double(customers$ID)
customers$Billing_Address <- as.double(customers$Billing_Address)
customers$Delivery_Address <- as.double(customers$Delivery_Address)
addresses$ID <- as.double(addresses$ID)
orders$ID <- as.double(orders$ID)
orders$Order_Customer <- as.double(orders$Order_Customer)
# for easy access, create separate columns with date and date time
orders$OrderDateTime <- ymd_hms(orders$OrderDate)
orders$OrderDate <- ymd(format(ymd_hms(orders$OrderDate),"%Y-%m-%d"))
Als Nächstes verwenden wir die dplyr-Bibliothek, um die empfangenen Daten zu bearbeiten. Mit dplyr können Sie Daten filtern, neue Spalten hinzufügen, bestimmte Spalten auswählen und die Zeilen sortieren, ganz ähnlich wie Sie es mit SQL in einer regulären Datenbank tun würden.
Der folgende dplyr-Ausdruck verbindet die Datenrahmen „Kunden“, „Adressen“ und „Bestellungen“.
customerOrders <- customers %>%
rename(CustomerID=ID) %>%
left_join(addresses, by=c("Delivery_Address"="ID")) %>%
select(CustomerID,Firstname,Lastname,City,Country) %>%
left_join(orders, by=c("CustomerID"="Order_Customer")) %>%
select(Firstname,Lastname,City,Country,OrderNumber)
Die ersten Zeilen dieses Datenrahmens sehen folgendermaßen aus:
customerOrders[1:5,]
## Firstname Lastname City Country OrderNumber
## 1 Ivan Freeman New Orleans US 1
## 2 Ivan Freeman New Orleans US 499
## 3 Anthony Robinson Brighton US 2
## 4 Anthony Robinson Brighton US 500
## 5 Kaden Griffith Bridgeport US 3
Nun können wir die Anzahl der Bestellungen pro Stadt wie folgt berechnen:
cityOrderCount <- customerOrders %>%
group_by(City) %>%
summarize(OrderCount = n()) %>%
arrange(desc(OrderCount))
Das Ergebnis:
cityOrderCount[1:5,]
## Source: local data frame [5 x 2]
##
## City OrderCount
## 1 New York 28
## 2 Philadelphia 16
## 3 Chicago 15
## 4 Miami 12
## 5 Baltimore 10
Erstellen von Diagrammen
Im folgenden Beispiel wird ggplot2 zum Erstellen von Diagrammen verwendet. Sie können auch andere Bibliotheken zum Erstellen von Diagrammen verwenden, aber ggplot2 ist eine der beliebtesten.
Wir beginnen mit einem einfachen Balkendiagramm, das die Anzahl der Bestellungen pro Monat darstellt.
library('ggplot2')
# Determine first day of month for every order, count number of orders per month
orderCount <- orders %>%
# Determine date of first day of the month, so ggplot understands it's a date
mutate(OrderMonth = ymd(format(OrderDate,"%Y-%m-01"))) %>%
group_by(OrderMonth) %>%
summarize(noOfOrders = n())
# generate barchart to display number of orders per month
ggplot() +
geom_bar(data=orderCount,aes(x=OrderMonth,y=noOfOrders), stat="identity") +
xlab("Month") +
ylab("Number of orders") +
ggtitle("Orders per month")

Als nächstes möchten wir wissen, wann in der Woche Bestellungen aufgegeben werden. Zunächst benötigen wir den Datensatz, der den Wochentag und die Uhrzeit jeder Bestellung enthält.
ordersPerWeekHour <- orders %>%
mutate(DayOfWeek = wday(OrderDate)) %>%
mutate(HourOfDay = hour(OrderDateTime)) %>%
group_by(DayOfWeek,HourOfDay) %>%
summarize(noOfOrders = n())
Für die eigentliche Grafik können wir nun verwenden Fliesenflugzeug um die Anzahl der Bestellungen für jede Stunde eines jeden Tages anzuzeigen. Wir setzen den Tag auf die X-Achse, die Stunde auf die Y-Achse und verwenden die Anzahl der Bestellungen, um die angezeigte Farbe zu bestimmen.
ggplot(ordersPerWeekHour, aes(x=DayOfWeek,y=HourOfDay))+
geom_tile(aes(fill=noOfOrders)) +
scale_fill_gradient(low="green", high="red") +
scale_x_continuous(breaks=1:7,labels=c("Sun","Mon","Tues","Wed","Thurs","Fri","Sat")) +
scale_y_continuous(breaks=0:24) +
labs(x="Day", y="Hour")

Sie erkennen nun deutlich, dass die meisten Bestellungen zwischen 16:00 und 22:00 Uhr eingehen, gleichmäßig verteilt auf alle Wochentage.
Generieren von Berichten mit R
R verfügt über einige interessante Berichtsfunktionen. Abschlagkönnen Sie HTML, Word, PDF oder sogar Folien direkt aus einem R-Bericht generieren.
Dieser ganze Blogbeitrag wurde tatsächlich mit rmarkdown geschrieben und erzeugte ein MS-Word-Dokument. Um das Word-Dokument mit den neuesten Daten aus meinem Mendix Anwendung muss ich nur das RMarkdown-Skript erneut ausführen.
Der einfachste Weg, mit Rmarkdown zu arbeiten, besteht darin, die integrierten Funktionen von RStudio zu verwenden. Alternativ können Sie einen Rmarkdown-Bericht auch ohne RStudio mit etwas R-Code erstellen:
library(knitr) # required for knitting from rmd to md
require(rmarkdown) # required for md to html
setwd('<location of your rmarkdown file>')
render("<name of the rmarkdown script>", "all")
Fazit
Die OData-Funktion in Mendix eröffnet viele Möglichkeiten für Mendix Benutzer. R ist ein leistungsstarkes Tool für statistische Analysen und Datenberichte. Mit OData Mendix Der Benutzer kann nun problemlos von all diesen Einrichtungen profitieren.