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)
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