ich habe eine große Datenmenge, hier ist einmal ein Beispiel:
Code: Alles auswählen
| Seriennummer | Equipmentnummer || date1 | date2 |
| -------- | -------- || -------- | -------- |
| Value1 | Value2 ||2010-12-06| 2014-03-14 |
| Value1 | Value2 ||2014-04-13| 2017-10-01 |
| Value1 | Value2 ||2017-11-01| |
| Value3 | Value4 ||2010-12-06| 2011-03-14 |
| Value3 | Value4 ||2014-04-13| 2017-10-01 |
Code: Alles auswählen
grouping_data = data[["Seriennummer ", "Equipmentnummer "]]
group_ids = (
(grouping_data != grouping_data.shift()).any(axis="columns").cumsum()
)
result = data.loc[
group_ids.groupby(group_ids)
.filter(lambda group: len(group) >= 2)
.index
]
1. Kriterium: (2014-04-13) - (2014-03-14) <70
2. Kriterium (2014-03-14) - (2010-12-06) >900.
In diesem Schema soll verglichen werden, also dementsprechend dann auch (2017-11-01) - (2017-10-01).
Nur wenn diese Kriterien erfüllt sind, möchte ich die ganze Zeile beibehalten. Zur Info: die 70 und die 900 sollen Tage darstellen.
Der Output soll also wie folgt aussehen:
Code: Alles auswählen
| Seriennummer | Equipmentnummer || date1 | date2 |
| -------- | -------- || -------- | -------- |
| Value1 | Value2 ||2010-12-06| 2014-03-14 |
| Value1 | Value2 ||2014-04-13| 2017-10-01 |
| Value1 | Value2 ||2017-11-01| |
Ich hatte mich gefragt, ob mein Vorhaben auch ohne Schleifen realisiert werden kann, sondern mit pandas-Anweisung wie in meinem ersten Code. Über jegliche Tipps und Anregungen würde ich mich freuen:
Hier mein Code mit Kommentaren:
Code: Alles auswählen
import pandas as pd
import numpy as np
data = pd.DataFrame([['Value1', 'Value2','2010-12-06' , '2014-03-14'],
['Value1', 'Value2','2014-04-13', '2017-10-01'],
['Value1', 'Value2','2017-11-01',''],
['Value3', 'Value4', '2010-12-06', '2011-03-14'],
['Value3', 'Value4', '2014-04-13', '2017-10-01']], columns=['Seriennummer', 'Equipmentnummer', 'date1', 'date2'])
grouping_data = data[["Seriennummer", "Equipmentnummer"]]
group_ids = (
(grouping_data != grouping_data.shift()).any(axis="columns").cumsum()
)
result = data.loc[
group_ids.groupby(group_ids)
.filter(lambda group: len(group) >= 2)
.index
]
#Hinzufügen von 'value_pair' als Hilfszeile
#Die Daten für jede Seriennummer wird in eine Zeile geschrieben
result['value_pair'] = (result[['date1','date2']]).values.tolist()
data_grouped = result.groupby(['Seriennummer','Equipmentnummer'])['value_pair'].apply(list).reset_index()
data_grouped = pd.concat([data_grouped.iloc[-1:], data_grouped.iloc[:-1]], axis=0).reset_index(drop=True)
#Um aus dem Array ne Liste zu machen und somit besser draufzugreifen können
data_grouped['value_pair'] = data_grouped[['value_pair']].applymap(np.concatenate)
#Definition der beiden Kriterien
A, B, C, D, E =1, 2, 3, 4, 5
#Abstand zwischen den Tagen horizontal nebeneinander: >900 Tage
#Abstand zwischen den Tagen horizontal nebeneinander: <70 Tage
def diff(lst, gap1=70, gap2=900):
ats, bts, cts, dts, ets = lst[A-1], lst[B-1], lst[C-1], lst[D-1], None
if len(lst) > 4:
ets = lst[E-1]
try:
condition1 = (cts - bts).days < gap1 if (cts and bts) else False
condition2 = (bts - ats).days > gap2 if (bts and ats) else False
if len(lst) > 4:
condition3 = (ets - dts).days < gap1 if (ets and dts) else False
condition4 = (dts - cts).days > gap2 if (dts and cts) else False
return (condition1 and condition2) and (condition3 and condition4)
else:
return condition1 and condition2
except IndexError:
return False
#Anwenden der beiden Kriterien
m = [diff(list(map(lambda x: pd.to_datetime(x), lst))) for lst in data_grouped["value_pair"]]
out = data_grouped.loc[m]
#convert to datetime
def convert_to_datetime(value_list):
# Convert None to NaT for datetime compatibility
value_list = [pd.NaT if v is None else pd.to_datetime(v) for v in value_list]
return value_list
#.copy da es sonst nicht funktioniert; hier hab ich den leichten Weg genommen
out = out.copy()
out['value_pair'] = out['value_pair'].apply(convert_to_datetime)
#convert to string
def to_str1(df1):
df1 = [None if v is pd.NaT else pd.to_datetime(v).strftime('%Y-%m-%d') for v in df1]
return df1
out['value_pair'] = out['value_pair'].apply(to_str1)
out['value_pair'] = out['value_pair'].apply(lambda x: [x[i:i+2] for i in range(0, len(x), 2)] if x is not None else None)
out = out.explode('value_pair').reset_index(drop=True)
# Spalte 'value_pair' in 'date1' und 'date2' aufteilen
out[['date1', 'date2']] = pd.DataFrame(out['value_pair'].tolist(), index=out.index)
# Die Spalte 'value_pair' entfernen
out = out.drop('value_pair', axis=1)
#Zusammemfügen des ursprünglichen dataframes (alle Spalten werden benötigt) mit den gewollten Zeilen aus out
df3 = data.merge(out, how="inner")
print(out)