Commit 90d06782 authored by tills's avatar tills
Browse files

Clean up

parent 6df313ae
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 4
}
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 4
}
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 4
}
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 4
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
delete me, just to keep the folder in git
\ No newline at end of file
%% Cell type:code id: tags:
``` python
import pandas as pd
import numpy as np
from pandas.io.json import json_normalize
import datetime
import os
```
%% Cell type:code id: tags:
``` python
# File Path of raw data
file_data=r'..\data\raw'
data_name=os.listdir(file_data)
write_to_path = r'..\data\preprocessed'
```
%% Cell type:code id: tags:
``` python
# Loads the raw json file for a specific container
def load_data(container):
file_number=file_data+'\\'+container+'.txt'
df = pd.read_json(file_number, lines=True)
raw_data = pd.DataFrame(df[1][0])
return raw_data
```
%% Cell type:code id: tags:
``` python
# Reverses the dataframe passed into the function
# The loaded raw data is in wrong historical order (Youngest date is the first entry)
def reverse_data(raw_data):
reversed_data = raw_data.loc[::-1].reset_index(drop = True)
return reversed_data
```
%% Cell type:code id: tags:
``` python
# Decodes the json data in the 'decoded_data' column of the dataframe
# Also removes letters from the cloumns listed below and transfroms then into Integers
def dec_data(data):
df_decoded_data = pd.json_normalize(data.decoded_data)
data["time"]=pd.to_datetime(list(map(lambda st: str(st)[0:19],raw_data["created_at"])))
data["Height (cm)"] = df_decoded_data["sensor_data.Height 1"].str.replace("cm","").astype(int)
data["Height 1 (cm)"] = df_decoded_data["sensor_data.Height 1"].str.replace("cm","").astype(int)
data["Height 2 (cm)"] = df_decoded_data["sensor_data.Height 2"].str.replace("cm","").astype(int)
data["Height 3 (cm)"] = df_decoded_data["sensor_data.Height 3"].str.replace("cm","").astype(int)
data["Height 4 (cm)"] = df_decoded_data["sensor_data.Height 4"].str.replace("cm","").astype(int)
data["Voltage (mV)"] = df_decoded_data["sensor_data.Voltage"].str.replace("mV","").astype(int)
data["Temperature (C)"] = df_decoded_data["sensor_data.Temperature"].str.replace("C","").astype(int)
data["Tilt (Degree)"] = df_decoded_data["sensor_data.Tilt"].str.replace("Degree","").astype(int)
return data
```
%% Cell type:code id: tags:
``` python
# Removes outliers from the data
# TODO: Right now only temperature outliers are removed
# TODO: Smoothing
def remove_outliers(data):
for idx, row in data[data['Temperature (C)'] >= 150].iterrows():
if idx != 0:
new_value = data.iloc[idx-1]['Temperature (C)']
else:
new_value = data.iloc[idx+1]['Temperature (C)']
data.at[idx, 'Temperature (C)'] = new_value
return data
```
%% Cell type:code id: tags:
``` python
# Writes the dataframe into a .csv file
# Container specifies the name of the file
def write_preprocessed_data(container, data):
data.to_csv(path_or_buf=write_to_path+'/'+container+'.txt')
```
%% Cell type:code id: tags:
``` python
# Detects trash collections when sudden changes in Heigth occur
# TODO: improve algorith
# TODO: test on multiple container files
def detect_collection(data):
last_value= None
collections = []
limit = 0.25
for idx, row in data.iterrows():
if last_value != None:
height = row['Height (cm)']
created_at = row['unix_time']
difference = height - last_value
if difference > last_value*limit and height > 110:
collections.append(idx)
last_value = row['Height (cm)']
return collections
```
%% Cell type:code id: tags:
``` python
weather_data = pd.read_excel(r'..\data\additional data\additional_data.xlsx')
weather_data
```
%%%% Output: execute_result
MESS_DATUM Temperatur Relative Feuchte Niederschlagsmenge \
0 2020-04-01 00:00:00 -0.6 57.0 0.0
1 2020-04-01 01:00:00 -1.0 58.0 0.0
2 2020-04-01 02:00:00 0.5 54.0 0.0
3 2020-04-01 03:00:00 -1.1 62.0 0.0
4 2020-04-01 04:00:00 -0.1 58.0 0.0
... ... ... ... ...
10219 2021-05-31 19:00:00 19.0 40.0 0.0
10220 2021-05-31 20:00:00 16.2 49.0 0.0
10221 2021-05-31 21:00:00 13.4 60.0 0.0
10222 2021-05-31 22:00:00 12.2 66.0 0.0
10223 2021-05-31 23:00:00 12.3 68.0 0.0
Feiertag Wochentag Frei[1/0]
0 0 Mittwoch 0
1 0 Mittwoch 0
2 0 Mittwoch 0
3 0 Mittwoch 0
4 0 Mittwoch 0
... ... ... ...
10219 0 Montag 0
10220 0 Montag 0
10221 0 Montag 0
10222 0 Montag 0
10223 0 Montag 0
[10224 rows x 7 columns]
%% Cell type:code id: tags:
``` python
def get_collection_data(data, collections):
collections_data = []
weather_data = pd.read_excel(r'..\data\additional data\additional_data.xlsx')
for collection in collections:
idx = collections.index(collection)
row = data.iloc[collection]
collection_data = {}
last_collection = 0
if idx != 0:
last_collection = collections[idx-1]
# Get data since last collection and data of last collection
data_since_last_collection = data.iloc[last_collection:collection]
data_last_collection = data.iloc[last_collection]
data_last_measurement = data.iloc[collection-1]
# Calculate time difference
collection_time = datetime.datetime.fromtimestamp(int(row['unix_time'])/1000)
last_collection_time = datetime.datetime.fromtimestamp(int(data_last_collection['unix_time'])/1000)
time_difference = last_collection_time-collection_time
# Weather Data
weather_data_since_last_collection = weather_data[(weather_data['MESS_DATUM'] <= collection_time) & (weather_data['MESS_DATUM'] >= last_collection_time)]
holiday_count = len(weather_data_since_last_collection[weather_data_since_last_collection['Frei[1/0]']==1].index)/len(weather_data_since_last_collection.index)
# Create collection data entry
collection_data['timestamp'] = row['created_at']
collection_data['container_id'] = row['deveui']
collection_data['last_collection'] = time_difference.days
collection_data['pre_height'] = data_last_measurement['Height (cm)']
collection_data['post_height'] = row['Height (cm)']
collection_data['sensor_mean_temperature'] = data_since_last_collection['Temperature (C)'].mean()
collection_data['sensor_max_temperature'] = data_since_last_collection['Temperature (C)'].max()
collection_data['sensor_min_temperature'] = data_since_last_collection['Temperature (C)'].min()
collection_data['weather_mean_temperature'] = weather_data_since_last_collection['Temperatur'].mean()
collection_data['weather_max_temperature'] = weather_data_since_last_collection['Temperatur'].max()
collection_data['weather_min_temperature'] = weather_data_since_last_collection['Temperatur'].min()
collection_data['weather_mean_rain'] = weather_data_since_last_collection['Niederschlagsmenge'].mean()
collection_data['weather_max_rain'] = weather_data_since_last_collection['Niederschlagsmenge'].max()
collection_data['weather_min_rain'] = weather_data_since_last_collection['Niederschlagsmenge'].min()
collection_data['weather_mean_moisture'] = weather_data_since_last_collection['Relative Feuchte'].mean()
collection_data['weather_max_moisture'] = weather_data_since_last_collection['Relative Feuchte'].max()
collection_data['weather_min_moisture'] = weather_data_since_last_collection['Relative Feuchte'].min()
collection_data['holiday_percentage'] = holiday_count
collection_data['year'] = collection_time.year
collection_data['month'] = collection_time.month
collection_data['weekday'] = collection_time.weekday()
collections_data.append(collection_data)
return collections_data
```
%% Cell type:code id: tags:
``` python
# Each raw data file gets processed and the written into a new file in data/preprocessed
collection_df = pd.DataFrame()
for file in data_name:
container_id = file.replace('.txt', '')
raw_data = load_data(container_id)
reversed_data = reverse_data(raw_data)
decoded_data = dec_data(reversed_data)
preprocessed = remove_outliers(decoded_data)
collections = detect_collection(decoded_data)
collections_data = get_collection_data(decoded_data, collections)
collection_df = collection_df.append(collections_data, ignore_index=True, sort=False)
#write_preprocessed_data(container_id, preprocessed)
```
%% Cell type:code id: tags:
``` python
# Write all available colletion data into one file in data/preprocessed
collection_df.to_csv(path_or_buf=write_to_path+'/collection_data.txt')
```
%% Cell type:code id: tags:
``` python
```
%% Cell type:code id: tags:
``` python
import pandas as pd
import numpy as np
import os
path_collection_data = '..\data\preprocessed\collection_data.txt'
df = pd.read_csv(path_collection_data)
```
%% Cell type:code id: tags:
``` python
df.head()
```
%%%% Output: execute_result
Unnamed: 0 timestamp container_id last_collection \
0 0 2020-05-22 18:51:01.742945 70B3D500700016DA -14
1 1 2020-06-05 14:49:42.681218 70B3D500700016DA -14
2 2 2020-06-29 13:47:52.050553 70B3D500700016DA -24
3 3 2020-07-17 13:46:18.287249 70B3D500700016DA -18
4 4 2020-08-07 09:44:36.149679 70B3D500700016DA -21
pre_height post_height sensor_mean_temperature sensor_max_temperature \
0 4 124 15.251029 47
1 20 126 16.410714 44
2 4 126 18.255446 43
3 12 128 19.053476 45
4 22 126 21.981524 47
sensor_min_temperature weather_mean_temperature ... weather_mean_rain \
0 0 14.283636 ... 0.037879
1 4 16.873193 ... 0.065964
2 4 18.670261 ... 0.043130
3 7 19.258796 ... 0.029167
4 6 21.973000 ... 0.020600
weather_max_rain weather_min_rain weather_mean_moisture \
0 1.8 0.0 58.121212
1 7.8 0.0 53.888554
2 10.2 0.0 65.890435
3 1.3 0.0 58.773148
4 4.2 0.0 49.794000
weather_max_moisture weather_min_moisture holiday_percentage year \
0 95.0 25.0 0.360606 2020
1 93.0 19.0 0.361446 2020
2 97.0 25.0 0.375652 2020
3 96.0 22.0 0.222222 2020
4 95.0 20.0 0.288000 2020
month weekday
0 5 4
1 6 4
2 6 0
3 7 4
4 8 4
[5 rows x 22 columns]
%% Cell type:code id: tags:
``` python
df.info()
```
%%%% Output: stream
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4118 entries, 0 to 4117
Data columns (total 22 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Unnamed: 0 4118 non-null int64
1 timestamp 4118 non-null object
2 container_id 4118 non-null object
3 last_collection 4118 non-null object
4 pre_height 4118 non-null int64
5 post_height 4118 non-null int64
6 sensor_mean_temperature 4118 non-null float64
7 sensor_max_temperature 4118 non-null int64
8 sensor_min_temperature 4118 non-null int64
9 weather_mean_temperature 4118 non-null float64
10 weather_max_temperature 4118 non-null float64
11 weather_min_temperature 4118 non-null float64
12 weather_mean_rain 4118 non-null float64
13 weather_max_rain 4118 non-null float64
14 weather_min_rain 4118 non-null float64
15 weather_mean_moisture 4118 non-null float64
16 weather_max_moisture 4118 non-null float64
17 weather_min_moisture 4118 non-null float64
18 holiday_percentage 4118 non-null float64
19 year 4118 non-null int64
20 month 4118 non-null int64
21 weekday 4118 non-null int64
dtypes: float64(11), int64(8), object(3)
memory usage: 707.9+ KB
%% Cell type:code id: tags:
``` python
>>> from sklearn.svm import SVR
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.pipeline import make_pipeline
X = df[['last_collection',
'sensor_mean_temperature',
'sensor_max_temperature',
'sensor_min_temperature',
'weather_mean_temperature',
'weather_max_temperature',
'weather_min_temperature',
'weather_mean_rain',
'weather_max_rain',
'weather_min_rain',
'weather_mean_moisture',
'weather_max_moisture',
'weather_min_moisture',
'holiday_percentage',
'year',
'month',
'weekday']]
y = df['pre_height']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
regr = make_pipeline(StandardScaler(), SVR())
regr.fit(X_train, y_train)
pred = regr.predict(X_test)
```
%% Cell type:code id: tags:
``` python
X_train['last_collection'].shape
```
%%%% Output: execute_result
(2759,)
%% Cell type:code id: tags:
``` python
import matplotlib.pyplot as plt
# Plot outputs
plt.scatter(X_test['last_collection'], y_test, color='black')
plt.plot(X_test['last_collection'], pred, color='blue', linewidth=3)
plt.xticks(())
plt.yticks(())
plt.show()
```
%%%% Output: display_data
![](data:image/png;base64,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)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment