Beschreibung der Domäne, die auf Basis der relationalen DB gewünscht wird:
- Über unterschiedliche (auch in Stationen) können Buchungen betätigt werden.
- Jede Station hat einen Betreiber
- In einer Buchung wird ein Fahrzeug ausgeliehen.
- Das Fahrzeug wird von einer Station abgeholt und in einer Station abgegeben
- Jede Buchung ist einer Tarifklasse zugeordnet.
- Fahrzeuge haben Eigenschaften
- Stationen haben Eigenschaften
- Tarifklassen haben Eigenschaften
- Buchungen haben Eigenschaften
Entscheidungen
- Fahrzeug-[wird abgeholt]->Station
- Fahrzeug-[wird abgegeben]->Station
- Buchung-[bezieht sich]->Fahrzeug
- Firma-[betreibt]->Station
- Firma-[gehoert zu]-> Gruppe
- Buchung-[hat]->Tarifklasse
- Tarifklasse-[ist untergeordnet zu]->Haupttarif
- Fahrzeuge unterscheiden sich durch
- Marke
- Kraftstoff
- Buchungen unterscheiden sich durch
- Tarifklasse
- Fahrstrecke
- Buchungsquelle
- Tarifklassen unterscheiden sich durch
- Haupttarif
In [5]:
import pandas as pd
import numpy as np
In [64]:
def writeDsvFile(df, typeName, delimiter, columnsList, headerList):
filename = './output/' + typeName + '.dsv'
df.to_csv(filename, index = False, sep = delimiter, columns = columnsList, header = headerList)
def trimName(longName):
trimmedName = ''
if longName == np.nan:
trimmedName = 'nan'
else:
#print(longName)
#print(longName.split())
#print(longName.split()[0])
#print(longName[:longName.find(" ")])
trimmedName = repr(longName).replace(' ', '_').replace('(','').replace(')','').replace('/','')
#print(trimmedName)
return trimmedName
In [131]:
def getLabel(row, nodeName):
switcher = {
"CATEGORY": "TARIF",
"PARENT_CATEGORY": "HAUPTTARIF",
"BOOKING": "BUCHUNG",
"VEHICLE": "FAHRZEUG",
"RENTAL_ZONE": "STATION"
}
label = switcher.get(nodeName, 'OBJ')
if nodeName == 'BOOKING':
label += ";" + str(row["PARENT_CATEGORY"])
elif nodeName == 'VEHICLE':
label += \
";" + str(row["VEHICLE_MODEL_TYPE"].upper()) + \
";" + str(row["VEHICLE_MANUFACTURER_NAME"].upper()) + \
";" + str(row["FUEL_TYPE_NAME"].upper());
elif nodeName == 'RENTAL_ZONE':
label += ";" + str(row["TYPE"].upper())
label += ";ACTIVE" if str(row["ACTIVE_X"].upper()) == "JA" else ";INACTIVE"
return label
In [77]:
def getRelationshipType(row, types):
switcher = {
"CATEGORY": {
"PARENT_CATEGORY": "GEHOERT_ZU",
},
"BOOKING": {
"VEHICLE": "BEZIEHT_SICH",
},
}
relType = switcher.get(types[0], {}).get(types[1], 'UNDEFINED')
return relType
In [138]:
df_cat = pd.read_csv('./datasets/OPENDATA_CATEGORY_CARSHARING.csv', quotechar='"',encoding ='utf-8', sep=';')
df_cat.head()
Out[138]:
Vorgehensweise:
- Wir wollen auch ein Label für die Buchungen realisieren, um für die Analyse eine einfacheres Mittel zu haben.
- Aus dem Grund macht es Sinn, neben den Tarifen auch Haupttarife zu definieren, die dann in einer Buchung als Label aufgeführt wird.
- Deswegen sind folgende Schritte notwendig
- Erster Schritt ist die Reduzierung der Tarifbezeichung auf ein Wort (als Name des Haupttarifs)
- Zweiter Schritt ist die Aufnahme in Buchung als zusätzliche Spalte
- Tarif und Haupttarife haben ein festes Label
- Teilen sich denselben Nummernsraum als Primärschlüssel
In [139]:
df_cat['LABEL'] = df_cat.apply(getLabel, axis=1, nodeName='CATEGORY')
df_cat.head()
Out[139]:
In [140]:
df_cat['PARENT_CATEGORY'] = df_cat.agg({'CATEGORY' : lambda x: x.split()[0].replace('/', '')})
df_cat.head()
Out[140]:
In [141]:
df_cat['PARENT_LABEL'] = df_cat.apply(getLabel, axis=1, nodeName='PARENT_CATEGORY')
df_cat.head()
Out[141]:
In [142]:
df_cat['PARENT_ID'] = df_cat.agg({'HAL_ID' : lambda x: x + 10000})
df_cat.head()
Out[142]:
In [143]:
df_cat['REL_TYPE_CAT_PCAT'] = df_cat.apply(getRelationshipType, axis=1, types=["CATEGORY","PARENT_CATEGORY"])
df_cat.head()
Out[143]:
In [144]:
# Die Nodes für die Tarife
writeDsvFile(df_cat, 'categories', '|', ['HAL_ID', 'CATEGORY', 'LABEL'], ['categoryID:ID(CATEGORY-ID)','name', ':LABEL'])
In [145]:
# Die Nodes für die Haupttarife
writeDsvFile(df_cat, 'parent_categories', '|', ['PARENT_ID', 'PARENT_CATEGORY', 'PARENT_LABEL'], ['categoryID:ID(CATEGORY-ID)','name', ':LABEL'])
In [146]:
# Beziehung zu den Haupttarifen
writeDsvFile(df_cat, 'rel_cat_pcat', '|', ['HAL_ID', 'PARENT_ID', 'REL_TYPE_CAT_PCAT'], [':START_ID(CATEGORY-ID)',':END_ID(CATEGORY-ID)', ':TYPE'])
In [91]:
df_fz = pd.read_csv('./datasets/OPENDATA_VEHICLE_CARSHARING.csv', quotechar='"',encoding ='utf-8', sep=';')
df_fz.head()
Out[91]:
Die Fahrzeuge haben sehr viele Eigenschaften. Nur einige davon eignen sich auch als Kategorisierungsmerkmal:
- VEHICLE_MODEL_TYPE -> Type
- VEHICLE_MANUFACTURER_NAME -> Marke
- FUEL_TYPE_NAME -> Kraftstoff
Andere Eigenschaften werden als Attribut aufgenommen.
Header für die Fahrzeuginformationen:
vehicleID:ID(VEHICLE-ID)|modelName|modelDetails|vin|registrationPlate|kw:long|fuelType|ownershipType|company|companyGroup|:LABEL
In [92]:
df_fz['LABEL'] = df_fz.apply(getLabel, axis=1, nodeName='VEHICLE')
df_fz.head()
Out[92]:
In [95]:
# Die Nodes für die Fahrzeuge
writeDsvFile(df_fz, 'vehicles', '|', ['VEHICLE_HAL_ID', 'VEHICLE_MODEL_NAME', 'VEHICLE_TYPE_NAME', 'VIN', 'REGISTRATION_PLATE', 'KW', 'FUEL_TYPE_NAME', 'OWNERSHIP_TYPE', 'COMPANY', 'COMPANY_GROUP', 'LABEL'], ['vehicleID:ID(VEHICLE-ID)','modelName','modelDetails','vin','registrationPlate','kw:long','fuelType','ownershipType','company','companyGroup',':LABEL'])
In [71]:
df_stations = pd.read_csv('./datasets/OPENDATA_RENTAL_ZONE_CARSHARING.csv', quotechar='"',encoding ='utf-8', sep=';')
df_stations.head()
Out[71]:
In [99]:
df_stations['RENTAL_ZONE_HAL_SRC'].unique()
Out[99]:
In [98]:
df_stations['COUNTRY'].unique()
Out[98]:
In [119]:
import functools as ft
ft.reduce( \
lambda x, y: x & y , \
map( \
lambda x: len(x.split())==1 \
, df_stations['CITY'].unique()) \
)
Out[119]:
In [125]:
list(filter( \
lambda x: len(x.split())>1 \
, df_stations['CITY'].unique() \
))
Out[125]:
In [100]:
df_stations['TYPE'].unique()
Out[100]:
In [132]:
df_stations['LABEL'] = df_stations.apply(getLabel, axis=1, nodeName='RENTAL_ZONE')
df_stations.head()
Out[132]:
In [135]:
# Die Nodes für die Fahrzeuge
writeDsvFile(df_stations, 'rentalZones', '|', \
['RENTAL_ZONE_HAL_ID', 'NAME', 'CODE', 'TYPE', 'CITY', 'LATITUDE', \
'LONGTITUDE', 'POI_AIRPORT_X', 'POI_LONG_DISTANCE_TRAINS_X', 'POI_SUBURBAN_TRAINS_X', \
'POI_UNDERGROUND_X', 'LABEL']\
, [ 'rentalZoneID:ID(RENTAL-ZONE-ID)', 'name', 'code', 'type', 'city', 'latitude:float', \
'longtitude:float', 'poiAirport', 'poiLongDistanceTrains', 'poiSuburbanTrains', \
'poiUnderground', ':LABEL'])
In [12]:
#df_cat.set_index("HAL_ID", inplace= True)
#df_cat.head()
In [13]:
df_booking = pd.read_csv('./datasets/OPENDATA_BOOKING_CARSHARING.csv', quotechar='"',encoding ='utf-8', sep=';')
df_booking.head()
Out[13]:
In [14]:
#List unique values in the df['name'] column
df_booking.TECHNICAL_INCOME_CHANNEL.unique()
Out[14]:
In [65]:
df_booking['INCOME_CHANNEL_NAME'] = df_booking.agg({'TECHNICAL_INCOME_CHANNEL' : lambda x: trimName(x)})
In [72]:
df_booking.INCOME_CHANNEL_NAME.head()
Out[72]:
In [17]:
df_booking.set_index("BOOKING_HAL_ID", inplace= True)
df_booking.head()
Out[17]:
Möglicher Umgang mit den Informationen über die Quelle (Technical income channel) der Bestellung:
Als Node mit weiteren Informationen/Beziehungen:
- Es liegen Detail-Informationen über die Quelle vor und die Informationen sind fachlich in Bezug auf die Haltung der Datenrelevant. Notwendige Aufwände:
- Integrieren der Detail-Informationen
- ID-Namespace für die Nodes
- Klärung der notwendige Beziehungen
Als Label in einer Buchung:
- Es liegen keine Detail-Informationen über die Quelle vor. Notwendige Aufwände:
- Die Quellbenennungen Label-Fähig machen (Reduktion auf ein Wort)
- Die Labelnamen als zusätzliche Spalte in df_booking aufnehmen.
In [152]:
df_cat_labels = df_cat.drop(['CATEGORY', 'COMPANY', 'COMPANY_GROUP', 'PARENT_LABEL', 'LABEL', 'PARENT_ID', 'REL_TYPE_CAT_PCAT'], axis=1)
df_booking_cat = pd.merge(df_booking, df_cat_labels, left_on='CATEGORY_HAL_ID', right_on='HAL_ID') \
.drop(['CUSTOMER_HAL_ID','HAL_ID','RENTAL_ZONE_HAL_SRC'], axis=1)
df_booking_cat.head()
Out[152]:
In [ ]: