Matroids Matheplanet Forum Index
Moderiert von matph
Informatik » Programmieren » Python: Filtern mit Pandas unter Berücksichtigung des Zeitstempels
Druckversion
Druckversion
Antworten
Antworten
Autor
Universität/Hochschule Python: Filtern mit Pandas unter Berücksichtigung des Zeitstempels
psigh
Aktiv Letzter Besuch: im letzten Monat
Dabei seit: 02.07.2010
Mitteilungen: 398
Zum letzten BeitragZum nächsten BeitragZum vorigen BeitragZum erstem Beitrag  Themenstart: 2020-04-02


Ich habe die Folgenden Testdaten:
python
import pandas as pd
import datetime
 
data = {'date': ['2014-01-01', '2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06', '2014-01-07'],
     'id': [1, 2, 2, 3, 4, 4, 5], 'name': ['Darren', 'Sabrina', 'Steve', 'Sean', 'Ray', 'Stef', 'Dany']}
data = pd.DataFrame(data)
data['date'] = pd.to_datetime(data['date'])

Die Frage ist: Gibt es, wenn man x Tage in die Vergangenheit schaut (von jedem einzelnen Eintrag aus gesehen), mehr als y verschiedene Namen, die dieselbe ID haben?

Hier ist meine Lösung. In meinem Beispiel gehe ich x = 2 Tage zurück und überprüfe, ob mindestens zwei unterschiedliche Namen (y = 1) dieselbe ID haben. Wenn mindestens zwei unterschiedliche Namen vorhanden sind, speichere ich 1 in der Liste "result_store", andernfalls 0. Natürlich ist in diesem Beispiel ein Zurückgehen von x Tagen nicht möglich, wenn i kleiner x ist, aber diese kleine Ungenauigkeit ist an dieser Stelle kein Problem.
python
def rule(data, x=2, y=1):
    result_store = []
    for i in range(data.shape[0]):
        id = data['id'][i]
        end_time = data['date'][i]
        start_time = end_time-datetime.timedelta(days=x)
        time_frame = data[(data['date'] >= start_time) &; (data['date'] < end_time)]
        time_frame = time_frame.loc[time_frame['id'] == id]
        distinct_names = time_frame['name'].nunique()
        if distinct_names > y:
            result_store.append(1)
        else:
            result_store.append(0)
 
    return result_store

Hier das Resultat:
python
[0, 0, 1, 0, 0, 1, 0]

In Wirklichkeit habe ich Tausende von Zeilen und meine Lösung ist extrem langsam. Ich habe auch versucht, über den Index i mit parmap zu parallelisieren, aber die Beschleunigung ist auch nicht zufriedenstellend. Gibt es eine effizientere Möglichkeit, zu diesem Erbgebnis zu kommen? Vielleicht mit pyspark?

Vielen Dank!




Eine Notiz zu diese Forumbeitrag schreiben Notiz   Profil  Quote  Link auf diesen Beitrag Link
schnitzel
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 26.02.2009
Mitteilungen: 174
Zum letzten BeitragZum nächsten BeitragZum vorigen BeitragZum erstem Beitrag  Beitrag No.1, eingetragen 2020-04-03


Hi,
es gibt verschieden Möglichkeiten.

1. die pandas Funktionen besser verwenden:
Für dich könnten die Funktionen rolling und groupby interessant sein. Ist es das was du willst?
python
import pandas as pd
import datetime
 
data = {'date': ['2014-01-01', '2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06', '2014-01-07'],
     'id': [1, 2, 2, 3, 4, 4, 5], 'name': range(7)}
 
#  pandas hat Probleme mit strings -> Name besser erst zu Integer machen
 
data = pd.DataFrame(data)
 
# date col als index
data['date'] = pd.to_datetime(data['date'])
data.index = data.date
data = data.drop('date', axis=1)
 
data.groupby('id')['name'].rolling('2d').apply(pd.Series.nunique, raw=False) >= 2

Ergibt:
id  date      
1   2014-01-01    False
2   2014-01-02    False
    2014-01-03     True
3   2014-01-04    False
4   2014-01-05    False
    2014-01-06     True
5   2014-01-07    False
Name: name, dtype: bool


2. numba: Besonders für Funktionen mit langen python Schleifen über numpy arrays geeignet. (auch mit gpu Möglichkeit)

3. Wenn dus fürchterlich übertreiben willst: dask mit cupy ; )

Gruß



Eine Notiz zu diese Forumbeitrag schreiben Notiz   Profil  Quote  Link auf diesen Beitrag Link
psigh
Aktiv Letzter Besuch: im letzten Monat
Dabei seit: 02.07.2010
Mitteilungen: 398
Zum letzten BeitragZum nächsten BeitragZum vorigen BeitragZum erstem Beitrag  Beitrag No.2, vom Themenstarter, eingetragen 2020-04-05


Super, vielen Dank!  Werde ich sofort ausprobieren. Ich habe es auch mal mit Pyspark versucht, aber das hat gewisse Nachteile. Denn am Ende der ganzen Prozedur, muss ich das Ergebnis mit .collect() wieder in ein numpy array überführen...und das dauert.

LG



Eine Notiz zu diese Forumbeitrag schreiben Notiz   Profil  Quote  Link auf diesen Beitrag Link
psigh
Aktiv Letzter Besuch: im letzten Monat
Dabei seit: 02.07.2010
Mitteilungen: 398
Zum letzten BeitragZum nächsten BeitragZum vorigen BeitragZum erstem Beitrag  Beitrag No.3, vom Themenstarter, eingetragen 2020-04-05


Bei näherer Betrachtung ist mir noch nicht klar geworden, warum ich name in integer umwandeln kann. Denn mir geht es ja um die Frage: Kam die id mehrfach vor UND waren die zugehörigen Namen unterschiedlich. Bei deiner Lösung wird, glaube ich, geschaut, ob die ids unterschiedlich waren.



Eine Notiz zu diese Forumbeitrag schreiben Notiz   Profil  Quote  Link auf diesen Beitrag Link
psigh
Aktiv Letzter Besuch: im letzten Monat
Dabei seit: 02.07.2010
Mitteilungen: 398
Zum letzten BeitragZum nächsten BeitragZum vorigen BeitragZum erstem Beitrag  Beitrag No.4, vom Themenstarter, eingetragen 2020-04-05


Hier noch mal ein besseres Beispiel. Denn hier kommen auch mal zwei ids innerhalb zwei Tagen vor, zu denen aber gleiche Namen gehören. Was man wohl machen könnte, wäre:
python
data = {'date': ['2014-01-01', '2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06', '2014-01-07'],
     'id': [1, 2, 2, 3, 4, 4, 5], 'name': ['Darren', 'Steve', 'Steve', 'Sean', 'Ray', 'Stef', 'Dany']}
 
#  pandas hat Probleme mit strings -> Name besser erst zu Integer machen
 
data = pd.DataFrame(data)
 
# date col als index
data['date'] = pd.to_datetime(data['date'])
data.index = data.date
data = data.drop('date', axis=1)
data["name"] = data.name.astype("category").cat.codes
 
test = data.groupby('id')["name"].rolling('2d').apply(pd.Series.nunique, raw=False) >= 2
 
 



Eine Notiz zu diese Forumbeitrag schreiben Notiz   Profil  Quote  Link auf diesen Beitrag Link
schnitzel
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 26.02.2009
Mitteilungen: 174
Zum letzten BeitragZum nächsten BeitragZum vorigen BeitragZum erstem Beitrag  Beitrag No.5, eingetragen 2020-04-05


Hi,

ja das meinte ich ja mit der Transformation str -> int. Bei deinem ersten Beispiel kamen eben nur unterschiedliche Namen vor.

Gruß



Eine Notiz zu diese Forumbeitrag schreiben Notiz   Profil  Quote  Link auf diesen Beitrag Link
psigh hat die Antworten auf ihre/seine Frage gesehen.
Neues Thema [Neues Thema] Antworten [Antworten]    Druckversion [Druckversion]

 


Wechsel in ein anderes Forum:
 Suchen    
 
All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest © 2001-2020 by Matroids Matheplanet
This web site was originally made with PHP-Nuke, a former web portal system written in PHP that seems no longer to be maintained nor supported. PHP-Nuke is Free Software released under the GNU/GPL license.
Ich distanziere mich von rechtswidrigen oder anstößigen Inhalten, die sich trotz aufmerksamer Prüfung hinter hier verwendeten Links verbergen mögen.
Lesen Sie die Nutzungsbedingungen, die Distanzierung, die Datenschutzerklärung und das Impressum.
[Seitenanfang]