[PYTHON] Deshalb habe ich Pandas verlassen [Data Science 100 Knock (Strukturierte Datenverarbeitung) # 3]

Deshalb habe ich Pandas verlassen [Data Science 100 Knock (Strukturierte Datenverarbeitung) # 3]

Wir werden das Python-Problem von [Data Science 100 Knock (Strukturierte Datenverarbeitung)] lösen (https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess). Diese Gruppe von Fragen verwendet Pandas für die Datenverarbeitung in der Modellantwort, aber wir werden sie nach dem Studium mit NumPy verarbeiten.

: arrow_up: Erster Artikel (# 1) : arrow_backward: Vorheriger Artikel (# 2) : arrow_forward: Nächster Artikel (# 4)

Einführung

Als Studie von NumPy werde ich das Python-Problem von [Data Science 100 Knock (Strukturierte Datenverarbeitung)] lösen (https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess).

Viele Leute, die mit Python datenwissenschaftliche Dinge tun, mögen Pandas-Liebhaber sein, aber tatsächlich können Sie dasselbe mit NumPy tun, ohne ** Pandas ** zu verwenden. Und NumPy ist normalerweise schneller. Als eine Person, die Pandas liebt, bin ich es immer noch nicht gewohnt, NumPy zu betreiben. Daher möchte ich versuchen, einen Abschluss von Pandas zu machen, indem ich diesen "Data Science 100 Knock" mit NumPy betreibe.

Dieses Mal werde ich die 17. bis 22. Frage stellen. Dieser Bereich scheint das Thema der Sortierung und Rangfolge zu sein. Die Anfangsdaten wurden wie folgt gelesen. Es ist eine Richtlinie, Funktionen nicht mit "np.vectorize ()" oder "np.frompyfunc ()" zu vektorisieren.

import numpy as np
import pandas as pd
from numpy.lib import recfunctions as rfn

#Für Modellantwort
df_customer = pd.read_csv('data/customer.csv')
df_receipt = pd.read_csv('data/receipt.csv')

#Daten, mit denen wir umgehen
arr_customer = np.genfromtxt(
    'data/customer.csv', delimiter=',', encoding='utf-8',
    names=True, dtype=None)
arr_receipt = np.genfromtxt(
    'data/receipt.csv', delimiter=',', encoding='utf-8',
    names=True, dtype=None)

P_017

P-17: Sortieren Sie den Kundendatenrahmen (df_customer) nach Geburtsdatum (geburtstag) in chronologischer Reihenfolge und zeigen Sie alle ersten 10 Elemente an.

Wenn Sie das Array sortieren möchten, verwenden Sie np.sort (), wodurch das sortierte Array zurückgegeben wird. Dieses Mal möchte ich die Sortierreihenfolge, also benutze "np.argsort ()" oder "np.ndarray.argsort ()". Es gibt auch eine Möglichkeit, den Spaltennamen an das Argument "order" von "np.sort ()" zu übergeben, dies wird jedoch nicht empfohlen, da das Verhalten nicht gut ist.

In[017]


arr_customer[arr_customer['birth_day'].argsort()][:10]

Out[017]


array([('CS003813000014', 'Nanami Murayama', 1, 'Weiblich', '1928-11-26', 90, '182-0007', 'Kikunodai, Chofu-Stadt, Tokio**********', 'S13003', 20160214, '0-00000000-0'),
       ('CS026813000004', 'Yoshimura Chaoyang', 1, 'Weiblich', '1928-12-14', 90, '251-0043', 'Motomachi Tsujido, Stadt Fujisawa, Präfektur Kanagawa**********', 'S14026', 20150723, '0-00000000-0'),
       ('CS018811000003', 'Misato Kumazawa', 1, 'Weiblich', '1929-01-07', 90, '204-0004', 'Noshio, Kiyose City, Tokio**********', 'S13018', 20150403, '0-00000000-0'),
       ('CS027803000004', 'Takuro Uchimura', 0, 'männlich', '1929-01-12', 90, '251-0031', 'Kugenuma Fujigaya, Stadt Fujisawa, Präfektur Kanagawa**********', 'S14027', 20151227, '0-00000000-0'),
       ('CS013801000003', 'Takuro Amano', 0, 'männlich', '1929-01-15', 90, '274-0824', 'Maehara Higashi, Stadt Funabashi, Präfektur Chiba**********', 'S12013', 20160120, '0-00000000-0'),
       ('CS001814000022', 'Riho Tsuruta', 1, 'Weiblich', '1929-01-28', 90, '144-0045', 'Minami Rokugo, Ota-ku, Tokio**********', 'S13001', 20161012, 'A-20090415-7'),
       ('CS016815000002', 'Miki Yamamoto', 1, 'Weiblich', '1929-02-22', 90, '184-0005', 'Sakuramachi, Koganei City, Tokio**********', 'S13016', 20150629, 'C-20090923-C'),
       ('CS009815000003', 'Riho Nakata', 1, 'Weiblich', '1929-04-08', 89, '154-0014', 'Shinmachi, Setagaya-ku, Tokio**********', 'S13009', 20150421, 'D-20091021-E'),
       ('CS005813000015', 'Erika Kanaya', 1, 'Weiblich', '1929-04-09', 89, '165-0032', 'Sagimiya, Nakano-ku, Tokio**********', 'S13005', 20150506, '0-00000000-0'),
       ('CS012813000013', 'Uno Minami Tomo', 1, 'Weiblich', '1929-04-09', 89, '231-0806', 'Honmoku-cho, Naka-ku, Yokohama-shi, Kanagawa**********', 'S14012', 20150712, '0-00000000-0')],
      dtype=[('customer_id', '<U14'), ('customer_name', '<U10'), ('gender_cd', '<i4'), ('gender', '<U2'), ('birth_day', '<U10'), ('age', '<i4'), ('postal_cd', '<U8'), ('address', '<U26'), ('application_store_cd', '<U6'), ('application_date', '<i4'), ('status_cd', '<U12')])

Time[017]


%timeit df_customer.sort_values('birth_day', ascending=True).head(10)
# 21.8 ms ± 346 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit arr_customer[arr_customer['birth_day'].argsort()][:10]
# 17.1 ms ± 473 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

P_018

P-18: Sortieren Sie den Kundendatenrahmen (df_customer) nach Geburtsdatum (geburtstag) in aufsteigender Reihenfolge und zeigen Sie alle ersten 10 Elemente an.

Kehren Sie einfach die Reihenfolge um.

In[018]


arr_customer[arr_customer['birth_day'].argsort()][::-1][:10]

Out[018]


array([('CS035114000004', 'Misato Omura', 1, 'Weiblich', '2007-11-25', 11, '156-0053', 'Sakura, Setagaya-ku, Tokio**********', 'S13035', 20150619, '6-20091205-6'),
       ('CS022103000002', 'Fukuyama Hajime', 9, 'Unbekannt', '2007-10-02', 11, '249-0006', 'Zushi, Zushi City, Präfektur Kanagawa**********', 'S14022', 20160909, '0-00000000-0'),
       ('CS002113000009', 'Mayuko Shibata', 1, 'Weiblich', '2007-09-17', 11, '184-0014', 'Nukii Minamimachi, Stadt Koganei, Tokio**********', 'S13002', 20160304, '0-00000000-0'),
       ('CS004115000014', 'Kyoko Matsui', 1, 'Weiblich', '2007-08-09', 11, '165-0031', 'Kamisagimiya, Nakano-ku, Tokio**********', 'S13004', 20161120, '1-20081231-1'),
       ('CS002114000010', 'Haruka Yamauchi', 1, 'Weiblich', '2007-06-03', 11, '184-0015', 'Nukii Kitamachi, Stadt Koganei, Tokio**********', 'S13002', 20160920, '6-20100510-1'),
       ('CS025115000002', 'Natsuki Koyanagi', 1, 'Weiblich', '2007-04-18', 11, '245-0018', 'Stadt Kamiida, Gemeinde Izumi, Stadt Yokohama, Präfektur Kanagawa**********', 'S14025', 20160116, 'D-20100913-D'),
       ('CS002113000025', 'Manami Hirosue', 1, 'Weiblich', '2007-03-30', 12, '184-0015', 'Nukii Kitamachi, Stadt Koganei, Tokio**********', 'S13002', 20171030, '0-00000000-0'),
       ('CS033112000003', 'Miki Nagano', 1, 'Weiblich', '2007-03-22', 12, '245-0051', 'Stadt Nase, Bezirk Totsuka, Stadt Yokohama, Präfektur Kanagawa**********', 'S14033', 20150606, '0-00000000-0'),
       ('CS007115000006', 'Fukuoka Shun', 1, 'Weiblich', '2007-03-10', 12, '285-0845', 'Nishishizu, Stadt Sakura, Präfektur Chiba**********', 'S12007', 20151118, 'F-20101016-F'),
       ('CS014113000008', 'Rio Yaguchi', 1, 'Weiblich', '2007-03-05', 12, '260-0041', 'Higashi Chiba, Chuo-ku, Stadt Chiba, Präfektur Chiba**********', 'S12014', 20150622, '3-20091108-6')],
      dtype=[('customer_id', '<U14'), ('customer_name', '<U10'), ('gender_cd', '<i4'), ('gender', '<U2'), ('birth_day', '<U10'), ('age', '<i4'), ('postal_cd', '<U8'), ('address', '<U26'), ('application_store_cd', '<U6'), ('application_date', '<i4'), ('status_cd', '<U12')])

P_019

P-19: Geben Sie dem Datenrahmen für Belegdetails (df_receipt) in absteigender Reihenfolge des Verkaufsbetrags (Betrag) pro Artikel Ränge und extrahieren Sie die ersten 10 Artikel. Artikel sollten Kunden-ID (customer_id), Verkaufsbetrag (Betrag) und zugewiesenen Rang anzeigen. Ist der Verkaufsbetrag gleich, wird die gleiche Rangfolge angegeben.

Es ist einfach, nach dem höchsten Umsatz zu sortieren.

sorted_array = arr_receipt[['customer_id', 'amount']][
    arr_receipt['amount'].argsort()[::-1]]

sorted_array[:10]
# array([('CS011415000006', 10925), ('ZZ000000000000',  6800),
#        ('CS028605000002',  5780), ('ZZ000000000000',  5480),
#        ('ZZ000000000000',  5480), ('CS015515000034',  5480),
#        ('CS021515000089',  5440), ('ZZ000000000000',  5440),
#        ('ZZ000000000000',  5280), ('ZZ000000000000',  5280)],
#       dtype={'names':['customer_id','amount'], 'formats':['<U14','<i4'], 'offsets':[40,140], 'itemsize':144})

Rang diesen Verkaufsbetrag. Am einfachsten ist es, scipy.stats.rankdata () zu verwenden. Diesmal fragen wir nach den meisten, aber diese Funktion gibt die Rangfolge in aufsteigender Reihenfolge zurück. Subtrahieren Sie also vom Maximalwert und drehen Sie ihn um.

import scipy.stats

rank_asc = scipy.stats.rankdata(sorted_array['amount'], 'max')
rank = rank_asc.max() - rank_asc + 1

rank[:10]
# array([1, 2, 3, 4, 4, 4, 7, 7, 9, 9], dtype=int64)

Wenn Sie die Funktion "scipy.stats.rankdata ()" nicht verwenden, überprüfen Sie, ob derselbe Rang vorhanden ist, und sagen Sie "Was ist der größte Wert in jeder Zeile" und "Was ist der n-te größte Wert". Erstellen Sie ein Array, um ein Rangarray zu erstellen.

#False, wenn es den gleichen Rang wie die nächsthöhere Reihe hat, andernfalls True
rank_cutidx = np.concatenate(
    ([True], sorted_array['amount'][1:] != sorted_array['amount'][:-1]))

# rank_cutidx.cumsum()-1: Ein Array mit dem höchsten Wert jeder Zeile
# rank_cutidx.nonzero(): Ein Array, das die Nummer jedes "n-ten größten Werts" angibt.
rank = rank_cutidx.nonzero()[0][rank_cutidx.cumsum()-1] + 1

rank[:10]
# array([1, 2, 3, 4, 4, 4, 7, 7, 9, 9], dtype=int64)

Ich benutze numpy.lib.recfunctions.append_fields (), um Spalten hinzuzufügen, aber diese Funktion war extrem langsam (es scheint, ein neues Array von Grund auf neu zu erstellen).

In[019]


sorted_array = arr_receipt[['customer_id', 'amount']][
    arr_receipt['amount'].argsort()[::-1]]
rank_cutidx = np.concatenate(
    ([True], sorted_array['amount'][1:] != sorted_array['amount'][:-1]))
rank = rank_cutidx.nonzero()[0][rank_cutidx.cumsum()-1]+1
rfn.append_fields(sorted_array, 'ranking', rank,
                  dtypes=rank.dtype, usemask=False)[:10]

Dann sollten Sie selbst einen leeren Tisch vorbereiten ...?

In[019]


sorter_index = arr_receipt['amount'].argsort()[::-1]
sorted_id = arr_receipt['customer_id'][sorter_index]
sorted_amount = arr_receipt['amount'][sorter_index]
rank_cutidx = np.concatenate(
    ([True], sorted_amount[1:] != sorted_amount[:-1]))
rank = rank_cutidx.nonzero()[0][rank_cutidx.cumsum()-1]+1

#Anordnung
new_arr = np.empty(arr_receipt.size, dtype=[('customer_id', sorted_id.dtype),
                                            ('amount', sorted_amount.dtype),
                                            ('ranking', rank.dtype)])
new_arr['customer_id'] = sorted_id
new_arr['amount'] = sorted_amount
new_arr['ranking'] = rank
new_arr[:10]

Out[019]


array([('CS011415000006', 10925, 1), ('ZZ000000000000',  6800, 2),
       ('CS028605000002',  5780, 3), ('ZZ000000000000',  5480, 4),
       ('ZZ000000000000',  5480, 4), ('CS015515000034',  5480, 4),
       ('CS021515000089',  5440, 7), ('ZZ000000000000',  5440, 7),
       ('ZZ000000000000',  5280, 9), ('ZZ000000000000',  5280, 9)],
      dtype=[('customer_id', '<U14'), ('amount', '<i4'), ('ranking', '<i8')])

Time[019]


#Musterantwort
%%timeit
df_tmp = pd.concat([df_receipt[['customer_id', 'amount']],
                    df_receipt['amount'].rank(method='min', ascending=False)], axis=1)
df_tmp.columns = ['customer_id', 'amount', 'ranking']
df_tmp.sort_values('ranking', ascending=True).head(10)
# 35 ms ± 643 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

#Eine kleine Verbesserung in einer Zeile
%%timeit
df_receipt[['customer_id', 'amount']] \
    .assign(ranking=df_receipt['amount'].rank(method='min', ascending=False)) \
    .sort_values('ranking', ascending=True).head(10)
# 34.1 ms ± 943 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

# Numpy
%%timeit
tmp_amount = np.ascontiguousarray(arr_receipt['amount'])
sorter_index = tmp_amount.argsort()[::-1]
sorted_id = arr_receipt['customer_id'][sorter_index]
sorted_amount = tmp_amount[sorter_index]
rank_cutidx = np.concatenate(([True], sorted_amount[1:] != sorted_amount[:-1]))
rank = rank_cutidx.nonzero()[0][rank_cutidx.cumsum()-1]+1
new_arr = np.empty(arr_receipt.size, dtype=[('customer_id', sorted_id.dtype), ('amount', sorted_amount.dtype), ('ranking', rank.dtype)])
new_arr['customer_id'] = sorted_id
new_arr['amount'] = sorted_amount
new_arr['ranking'] = rank
new_arr[:10]
# 22.6 ms ± 464 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Ich habe es geschafft, es schneller als Pandas zu verarbeiten.

P_020

P-020: Geben Sie dem Datenrahmen für Belegdetails (df_receipt) in absteigender Reihenfolge des Verkaufsbetrags (Betrag) pro Artikel Ränge und extrahieren Sie die ersten 10 Artikel. Artikel sollten Kunden-ID (customer_id), Verkaufsbetrag (Betrag) und zugewiesenen Rang anzeigen. Geben Sie außerdem ein anderes Ranking an, auch wenn der Verkaufsbetrag (Betrag) gleich ist.

Dies ist eine Rangfolge oder nur eine Seriennummer mit np.arange ().

In[020]


rfn.append_fields(arr_receipt[['customer_id', 'amount']]
                  [arr_receipt['amount'].argsort()[::-1]],
                  'ranking', np.arange(1, arr_receipt.size+1),
                  dtypes='<i4', usemask=False)[:10]

In[020]


sorter_index = arr_receipt['amount'].argsort()[::-1]
sorted_id = arr_receipt['customer_id'][sorter_index]
sorted_amount = arr_receipt['amount'][sorter_index]
rank = np.arange(1, sorted_id.size+1)

#Anordnung
new_arr = np.empty(arr_receipt.size, dtype=[('customer_id', sorted_id.dtype),
                                            ('amount', sorted_amount.dtype),
                                            ('ranking', rank.dtype)])
new_arr['customer_id'] = sorted_id
new_arr['amount'] = sorted_amount
new_arr['ranking'] = rank
new_arr[:10]

Out[020]


array([('CS011415000006', 10925,  1), ('ZZ000000000000',  6800,  2),
       ('CS028605000002',  5780,  3), ('ZZ000000000000',  5480,  4),
       ('ZZ000000000000',  5480,  5), ('CS015515000034',  5480,  6),
       ('CS021515000089',  5440,  7), ('ZZ000000000000',  5440,  8),
       ('ZZ000000000000',  5280,  9), ('ZZ000000000000',  5280, 10)],
      dtype=[('customer_id', '<U14'), ('amount', '<i4'), ('ranking', '<i4')])

P_021

P-021: Zählen Sie die Anzahl der Fälle für den Belegdetaildatenrahmen (df_receipt).

In[021]


arr_receipt.size
len(arr_receipt)
arr_receipt.shape[0]

Out[021]


104681
104681
104681

P_022

P-022: Zählen Sie die Anzahl der eindeutigen Fälle für die Kunden-ID (customer_id) des Datenrahmens für Belegdetails (df_receipt).

Die eindeutige Anzahl der Zeichenfolgendaten ist für NumPy nicht gut.

In[022]


np.unique(arr_receipt['customer_id']).size

Out[022]


8307

Es ist bekannt, dass dies bei Pandas viel schneller ist als bei NumPy, wie Pandas in der offiziellen Dokumentation angeben, und wir, die NumPy-Piloten, können wahrscheinlich nicht anders.

Time[022]


%timeit len(df_receipt['customer_id'].unique())
# 8.19 ms ± 204 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit np.unique(arr_receipt['customer_id']).size
# 30.9 ms ± 635 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Recommended Posts

Deshalb habe ich Pandas verlassen [Data Science 100 Knock (Strukturierte Datenverarbeitung) # 2]
Deshalb habe ich Pandas verlassen [Data Science 100 Knock (Strukturierte Datenverarbeitung) # 1]
Deshalb habe ich Pandas verlassen [Data Science 100 Knock (Strukturierte Datenverarbeitung) # 3]
Deshalb habe ich Pandas verlassen [Data Science 100 Knock (Strukturierte Datenverarbeitung) # 5]
Deshalb habe ich Pandas verlassen [Data Science 100 Knock (Strukturierte Datenverarbeitung) # 4]
Deshalb habe ich Pandas verlassen [Data Science 100 Knock (Strukturierte Datenverarbeitung) # 6]
"Data Science 100 Knock (Strukturierte Datenverarbeitung)" Python-007 Erläuterung
"Data Science 100 Knock (Strukturierte Datenverarbeitung)" Python-001 Erläuterung
"Data Science 100 Knock (Strukturierte Datenverarbeitung)" Python-002 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 021 Erläuterung
"Data Science 100 Knock (Strukturierte Datenverarbeitung)" Python-005 Erläuterung
"Data Science 100 Knock (Strukturierte Datenverarbeitung)" Python-004 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 020 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 025 Erläuterung
"Data Science 100 Knock (Strukturierte Datenverarbeitung)" Python-003 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 019 Erläuterung
Vorbereitung zum Versuch "Data Science 100 Knock (Strukturierte Datenverarbeitung)"
Umgebungskonstruktion (Windows 10) für 100 Schläge Data Science (strukturierte Datenverarbeitung)
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 001-010 Impressionen + Zusammenfassung der Kommentare
Deshalb beende ich Pandas [Drei Möglichkeiten, um groupby.mean () mit nur NumPy]
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 018 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 023 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 030 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 022 Erläuterung
100 Sprachverarbeitung Knock-20 (unter Verwendung von Pandas): Lesen von JSON-Daten
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 017 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 026 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 016 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 024 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 027 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 029 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 015 Erläuterung
[Python] 100 Schläge auf Data Science (strukturierte Datenverarbeitung) 028 Erläuterung
Data Science 100 Klopfkommentar (P021 ~ 040)
Data Science 100 Klopfkommentar (P061 ~ 080)
Data Science 100 Klopfkommentar (P041 ~ 060)
Data Science 100 Klopfkommentar (P081 ~ 100)
Ich habe versucht, 100 Sprachverarbeitung klopfen 2020
Datenverarbeitungstipps mit Pandas
Ich habe versucht, 100 Sprachverarbeitung klopfen 2020: Kapitel 3
Sprachverarbeitung 100 Knocks-31 (mit Pandas): Verben
Ich habe versucht, 100 Sprachverarbeitung klopfen 2020: Kapitel 1
Ich habe versucht, 100 Sprachverarbeitung zu klopfen 2020: Kapitel 2
Ich habe versucht, 100 Sprachverarbeitung zu klopfen 2020: Kapitel 4
100 Sprachverarbeitung Knock-38 (mit Pandas): Histogramm
100 Sprachverarbeitung Knock-33 (mit Pandas): Sahen Nomen
100 Sprachverarbeitung Knock-91: Vorbereitung von Analogiedaten
Ich habe Udemys "Practical Python Data Science" ausprobiert.
100 Sprachverarbeitung Knock-35 (mit Pandas): Nomenklatur
100 Sprachverarbeitung Knock-39 (mit Pandas): Zipf-Gesetz
Beispiel für eine effiziente Datenverarbeitung mit PANDAS
100 Sprachverarbeitung Knock-34 (mit Pandas): "B von A"