Nous allons résoudre le problème Python de Data Science 100 Knock (traitement des données structurées). Ce groupe de questions utilise des pandas pour le traitement des données dans la réponse du modèle, mais nous le traiterons à l'aide de NumPy après étude.
: arrow_up: Premier article (# 1) : arrow_backward: article précédent (# 5) : arrow_forward: Article suivant (# 7)
En tant qu'étude de NumPy, je résoudrai le problème Python de Data Science 100 Knock (traitement des données structurées).
Beaucoup de gens qui font des activités de science des données avec Python sont peut-être des amateurs de pandas, mais en fait, vous pouvez faire de même avec NumPy sans utiliser ** pandas **. Et NumPy est généralement plus rapide. En tant que personne qui aime les pandas, je ne suis toujours pas habitué à utiliser NumPy, donc j'aimerais essayer de sortir des pandas en exploitant ce "Data Science 100 Knock" avec NumPy.
Cette fois, je répondrai aux 52e à 62e questions. Cela semble être le thème de la catégorisation des données. Les données initiales ont été lues comme suit.
import numpy as np
import pandas as pd
from numpy.lib import recfunctions as rfn
#Pour la réponse du modèle
df_customer = pd.read_csv('data/customer.csv')
df_receipt = pd.read_csv('data/receipt.csv')
#Données que nous traitons
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)
Enfin, une fonction pour sortir le résultat du calcul sous forme de tableau structuré
def make_array(size, **kwargs):
arr = np.empty(size, dtype=[(colname, subarr.dtype)
for colname, subarr in kwargs.items()])
for colname, subarr in kwargs.items():
arr[colname] = subarr
return arr
P_052
P-052: Montant total des ventes (montant) du bloc de données des détails du reçu (df_receipt) pour chaque ID client (customer_id), et 0 pour 2000 yens ou moins et 1 pour plus de 2000 yens pour le montant total des ventes. Ensuite, affichez 10 articles avec l'ID client et le montant total des ventes. Cependant, si l'ID client commence par "Z", il représente un non-membre, donc excluez-le du calcul.
Les ventes par client sont calculées par l'habituel np.unique ()
+ np.bincount ()
. "0 pour moins de 2000 yens et 1 pour plus de 2000" convertit simplement le tableau booléen par rapport à 2000 en une valeur numérique (False est équivalent à 0 et True est équivalent à 1).
In[052]
is_member = arr_receipt['customer_id'].astype('<U1') != 'Z'
unq_id, inv_id = np.unique(arr_receipt['customer_id'][is_member],
return_inverse=True)
amount_arr = np.bincount(inv_id, arr_receipt['amount'][is_member])
make_array(unq_id.size,
customer_id=unq_id,
amount=amount_arr,
sales_flg=(amount_arr > 2000).view(np.int8))[:10]
Out[052]
array([('CS001113000004', 1298., 0), ('CS001114000005', 626., 0),
('CS001115000010', 3044., 1), ('CS001205000004', 1988., 0),
('CS001205000006', 3337., 1), ('CS001211000025', 456., 0),
('CS001212000027', 448., 0), ('CS001212000031', 296., 0),
('CS001212000046', 228., 0), ('CS001212000070', 456., 0)],
dtype=[('customer_id', '<U14'), ('amount', '<f8'), ('sales_flg', 'i1')])
Time[052]
#Le modèle de réponse
%%timeit
df_sales_amount = df_receipt.query('not customer_id.str.startswith("Z")', engine='python')
df_sales_amount = df_sales_amount[['customer_id', 'amount']].groupby('customer_id').sum().reset_index()
df_sales_amount['sales_flg'] = df_sales_amount['amount'].apply(lambda x: 1 if x > 2000 else 0)
df_sales_amount.head(10)
# 72.9 ms ± 1.67 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
#Amélioration
%%timeit
df_sales_amount = df_receipt.loc[~df_receipt['customer_id'].str.startswith('Z'), ['customer_id', 'amount']].groupby('customer_id', as_index=False).sum()
df_sales_amount['sales_flg'] = (df_sales_amount['amount'] > 2000).astype(int)
df_sales_amount.head(10)
# 63.5 ms ± 226 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
#NumPy (voir code ci-dessus)
# 33.8 ms ± 252 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
P_053
P-053: Pour le postal_cd de la trame de données client (df_customer), binarisez Tokyo (les 3 premiers chiffres vont de 100 à 209) à 1 et les autres à 0. De plus, combinez-le avec le bloc de données du relevé de réception (df_receipt) et comptez le nombre de clients qui ont un enregistrement d'achat pour toute la période pour chacune des deux valeurs créées.
Tout d'abord, utilisez np.in1d ()
pour extraire uniquement les clients avec un historique d'achat. Ensuite, convertissez les 3 premiers chiffres du code postal en valeur numérique. Vous pouvez utiliser .astype ('<U3'). Astype (int)
, mais ici nous utilisons np.frombuffer ()
pour convertir sans passer par .astype ()
([P_011) ](Voir https://qiita.com/nkay/items/65a77b97ae9b7331b39c#p_011).
In[053]
isin_rec = np.in1d(arr_customer['customer_id'], arr_receipt['customer_id'])
post_int_arr = ((np.frombuffer(
arr_customer['postal_cd'][isin_rec].tobytes(), dtype=np.int32)
- 48).reshape(-1, 8)[:, :3]*np.array([100, 10, 1])).sum(1)
postal_flg = ((101 <= post_int_arr) & (post_int_arr <= 209))
make_array(2, postal_flg=np.arange(2), count=np.bincount(postal_flg))
Out[053]
array([(0, 3906), (1, 4400)],
dtype=[('postal_flg', '<i4'), ('count', '<i8')])
Time[053]
#Le modèle de réponse
%%timeit
df_tmp = df_customer[['customer_id', 'postal_cd']].copy()
df_tmp['postal_flg'] = df_tmp['postal_cd'].apply(lambda x: 1 if 100 <= int(x[0:3]) <= 209 else 0)
pd.merge(df_tmp, df_receipt, how='inner', on='customer_id').groupby('postal_flg').agg({'customer_id':'nunique'})
# 109 ms ± 4.89 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
#NumPy (voir code ci-dessus)
# 50.2 ms ± 349 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
P_054
P-054: L'adresse de la trame de données client (df_customer) est celle de la préfecture de Saitama, de la préfecture de Chiba, de la région métropolitaine de Tokyo et de la préfecture de Kanagawa. Créez une valeur de code pour chaque préfecture et extrayez-la avec l'ID client et l'adresse. Les valeurs doivent être 11 pour la préfecture de Saitama, 12 pour la préfecture de Chiba, 13 pour Tokyo et 14 pour la préfecture de Kanagawa. Vous pouvez afficher 10 résultats.
Regardez la première lettre de la colonne d'adresse et remplacez-la par n'importe quel nombre (voir [P_036](voir https://qiita.com/nkay/items/a77fcb2dd3810d1f20c3#p_036)).
In[054]
caps = np.array(['Sai', 'mille', 'est', 'Dieu'], dtype='<U1')
sorter_index = caps.argsort()
idx = np.searchsorted(caps, arr_customer['address'].astype('<U1'),
sorter=sorter_index)
address_code = np.array([11, 12, 13, 14])[sorter_index[idx]]
make_array(arr_customer.size,
customer_id=arr_customer['customer_id'],
address=arr_customer['address'],
address_code=address_code)[:10]
Out[054]
array([('CS021313000114', 'Awakubo, ville d'Isehara, préfecture de Kanagawa**********', 14),
('CS037613000071', 'Minamisago, Koto-ku, Tokyo**********', 13),
('CS031415000172', 'Yoyogi, Shibuya-ku, Tokyo**********', 13),
('CS028811000001', 'Izumi-cho, Izumi-ku, Yokohama-shi, Kanagawa**********', 14),
('CS001215000145', 'Nakarokugo, Ota-ku, Tokyo**********', 13),
('CS020401000016', 'Wakagi, Itabashi-ku, Tokyo**********', 13),
('CS015414000103', 'Kitasa, Koto-ku, Tokyo**********', 13),
('CS029403000008', 'Ville d'Urayasu, préfecture de Chiba**********', 12),
('CS015804000004', 'Kitasa, Koto-ku, Tokyo**********', 13),
('CS033513000180', 'Zenbe-cho, Asahi-ku, Yokohama-shi, Kanagawa**********', 14)],
dtype=[('customer_id', '<U14'), ('address', '<U26'), ('address_code', '<i4')])
Time[054]
#Le modèle de réponse
pd.concat([df_customer[['customer_id', 'address']],
df_customer['address'].str[0:3].map({'Saitama': '11', 'Préfecture de Chiba': '12', 'Tokyo': '13', 'Kanagawa': '14'})],
axis=1).head(10)
# 16.2 ms ± 963 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
#NumPy (voir code ci-dessus)
# 4.52 ms ± 176 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
P_055
P-055: Additionnez le montant des ventes (montant) du bloc de données de détail du reçu (df_receipt) pour chaque ID client (customer_id), et trouvez le quadrant du montant total. Ensuite, créez une valeur de catégorie pour le montant total des ventes pour chaque client en fonction des critères suivants et affichez à la fois l'ID client et le montant des ventes. Les valeurs de catégorie vont de 1 à 4 dans l'ordre du haut. Vous pouvez afficher 10 résultats.
--Valeur minimale ou supérieure et inférieure au premier quadrant
- Du premier quadrant à moins du deuxième quadrant
- Du deuxième quadrant à moins du troisième quadrant --Troisième quart et plus
Les ventes par client sont calculées par l'habituel np.unique ()
+ np.bincount ()
. Ensuite, utilisez np.quantile ()
pour trouver le quadrant. Enfin, comparez les ventes par client avec la valeur du quadrant pour savoir à quel groupe vous appartenez (vous pouvez également utiliser np.searchsorted ()
).
In[055]
unq_id, inv_id = np.unique(arr_receipt['customer_id'],
return_inverse=True)
amount_arr = np.bincount(inv_id, arr_receipt['amount'])
quantiles = np.quantile(amount_arr, np.arange(1, 4)/4)
pct_group = (quantiles[:, None] <= amount_arr).sum(0) + 1
make_array(unq_id.size,
customer_id=unq_id, amount=amount_arr, pct_group=pct_group)[:10]
Out[055]
array([('CS001113000004', 1298., 2), ('CS001114000005', 626., 2),
('CS001115000010', 3044., 3), ('CS001205000004', 1988., 3),
('CS001205000006', 3337., 3), ('CS001211000025', 456., 1),
('CS001212000027', 448., 1), ('CS001212000031', 296., 1),
('CS001212000046', 228., 1), ('CS001212000070', 456., 1)],
dtype=[('customer_id', '<U14'), ('amount', '<f8'), ('pct_group', '<i8')])
P_056
P-056: Calculez l'âge par incréments de 10 ans en fonction de l'âge de la base de données client (df_customer), et extrayez-la avec l'ID client (customer_id) et la date de naissance (date_anniversaire). Cependant, toutes les personnes âgées de plus de 60 ans devraient être dans la soixantaine. Le nom de la catégorie indiquant l'âge est arbitraire. Les 10 premiers éléments doivent être affichés.
In[056]
age = arr_customer['age']//10*10
age[age > 60] = 60
arr_customer_era = make_array(arr_customer.size,
customer_id=arr_customer['customer_id'],
birth_day=arr_customer['birth_day'],
age=age)
arr_customer_era[:10]
Vous pouvez également utiliser «np.clip ()» ou «np.where ()».
Out[056]
array([('CS021313000114', '1981-04-29', 30),
('CS037613000071', '1952-04-01', 60),
('CS031415000172', '1976-10-04', 40),
('CS028811000001', '1933-03-27', 60),
('CS001215000145', '1995-03-29', 20),
('CS020401000016', '1974-09-15', 40),
('CS015414000103', '1977-08-09', 40),
('CS029403000008', '1973-08-17', 40),
('CS015804000004', '1931-05-02', 60),
('CS033513000180', '1962-07-11', 50)],
dtype=[('customer_id', '<U14'), ('birth_day', '<U10'), ('age', '<i4')])
P_057
P-057: Combinez le résultat de l'extraction de la question précédente et le sexe (sexe), et créez de nouvelles données de catégorie qui représentent la combinaison du sexe et de l'âge. La valeur de la catégorie représentant la combinaison est arbitraire. Les 10 premiers éléments doivent être affichés.
In[057]
arr_customer_era = make_array(arr_customer.size,
customer_id=arr_customer['customer_id'],
birth_day=arr_customer['birth_day'],
age=age,
era_gender=arr_customer['gender_cd']*100+age)
arr_customer_era[:10]
Out[057]
array([('CS021313000114', '1981-04-29', 30, 130),
('CS037613000071', '1952-04-01', 60, 960),
('CS031415000172', '1976-10-04', 40, 140),
('CS028811000001', '1933-03-27', 60, 160),
('CS001215000145', '1995-03-29', 20, 120),
('CS020401000016', '1974-09-15', 40, 40),
('CS015414000103', '1977-08-09', 40, 140),
('CS029403000008', '1973-08-17', 40, 40),
('CS015804000004', '1931-05-02', 60, 60),
('CS033513000180', '1962-07-11', 50, 150)],
dtype=[('customer_id', '<U14'), ('birth_day', '<U10'), ('age', '<i4'), ('era_gender', '<i4')])
P_058
P-058: Faites du code de genre (gender_cd) de la trame de données client (df_customer) une variable fictive et extrayez-le avec l'ID client (customer_id). Vous pouvez afficher 10 résultats.
Broca.
In[058]
dummies = (arr_customer['gender_cd']
== np.array([[0], [1], [9]])).view(np.int8)
make_array(arr_customer.size,
customer_id=arr_customer['customer_id'],
gender_cd_0=dummies[0],
gender_cd_1=dummies[1],
gender_cd_9=dummies[2])[:10]
Out[058]
gender_cd = np.ascontiguousarray(arr_customer['gender_cd'])...
array([('CS021313000114', 0, 1, 0), ('CS037613000071', 0, 0, 1),
('CS031415000172', 0, 1, 0), ('CS028811000001', 0, 1, 0),
('CS001215000145', 0, 1, 0), ('CS020401000016', 1, 0, 0),
('CS015414000103', 0, 1, 0), ('CS029403000008', 1, 0, 0),
('CS015804000004', 1, 0, 0), ('CS033513000180', 0, 1, 0)],
dtype=[('customer_id', '<U14'), ('gender_cd_0', 'i1'), ('gender_cd_1', 'i1'), ('gender_cd_9', 'i1')])
P_059
P-059: Le montant total des ventes (montant) du bloc de données des détails du reçu (df_receipt) est totalisé pour chaque ID client (customer_id), et le montant total des ventes est normalisé à 0 moyen et l'écart type 1 à l'ID client total et au montant des ventes. Afficher avec. L'écart type utilisé pour la normalisation peut être soit un écart-type non biaisé, soit un écart-type d'échantillon. Cependant, si l'ID client commence par "Z", il représente un non-membre, donc excluez-le du calcul. Vous pouvez afficher 10 résultats.
Appliquez simplement à la formule. C'est facile avec scipy.stats.zscore ()
.
In[059]
is_member = arr_receipt['customer_id'].astype('<U1') != 'Z'
unq_id, inv_id = np.unique(arr_receipt['customer_id'][is_member],
return_inverse=True)
amount_arr = np.bincount(inv_id, arr_receipt['amount'][is_member])
amount_mean = amount_arr.mean()
amount_std = np.sqrt(((amount_arr-amount_mean)**2).mean())
amount_ss = (amount_arr - amount_mean) / amount_std
# amount_ss = scipy.stats.zscore(amount_mean)Mais d'accord
make_array(unq_id.size,
customer_id=unq_id, amount=amount_arr, amount_ss=amount_ss)[:10]
Out[059]
array([('CS001113000004', 1298., -0.45937788),
('CS001114000005', 626., -0.70639037),
('CS001115000010', 3044., 0.18241349),
('CS001205000004', 1988., -0.20574899),
('CS001205000006', 3337., 0.29011387),
('CS001211000025', 456., -0.76887864),
('CS001212000027', 448., -0.77181927),
('CS001212000031', 296., -0.82769114),
('CS001212000046', 228., -0.85268645),
('CS001212000070', 456., -0.76887864)],
dtype=[('customer_id', '<U14'), ('amount', '<f8'), ('amount_ss', '<f8')])
P_060
P-060: Le montant des ventes (montant) du bloc de données de détail de la réception (df_receipt) est totalisé pour chaque ID client (customer_id), et le montant total des ventes est normalisé à la valeur minimale 0 et la valeur maximale 1 à l'ID client et au montant des ventes. Afficher avec le total. Cependant, si l'ID client commence par "Z", il représente un non-membre, donc excluez-le du calcul. Vous pouvez afficher 10 résultats.
Appliquez simplement à la formule.
In[060]
is_member = arr_receipt['customer_id'].astype('<U1') != 'Z'
unq_id, inv_id = np.unique(arr_receipt['customer_id'][is_member],
return_inverse=True)
amount_arr = np.bincount(inv_id, arr_receipt['amount'][is_member])
amount_min, amount_max = amount_arr.min(), amount_arr.max()
amount_mm = (amount_arr - amount_min) / (amount_max - amount_min)
make_array(unq_id.size,
customer_id=unq_id, amount=amount_arr, amount_mm=amount_mm)[:10]
Out[060]
array([('CS001113000004', 1298., 0.05335419),
('CS001114000005', 626., 0.02415711),
('CS001115000010', 3044., 0.12921446),
('CS001205000004', 1988., 0.08333333),
('CS001205000006', 3337., 0.14194473),
('CS001211000025', 456., 0.01677094),
('CS001212000027', 448., 0.01642336),
('CS001212000031', 296., 0.00981926),
('CS001212000046', 228., 0.00686479),
('CS001212000070', 456., 0.01677094)],
dtype=[('customer_id', '<U14'), ('amount', '<f8'), ('amount_mm', '<f8')])
P_061
P-061: Le montant des ventes (montant) du bloc de données de détail du reçu (df_receipt) est totalisé pour chaque ID client (customer_id), et le montant total des ventes est converti en une valeur logarithmique normale (base = 10) pour totaliser l'ID client et le montant des ventes. Afficher avec. Cependant, si l'ID client commence par "Z", il représente un non-membre, donc excluez-le du calcul. Vous pouvez afficher 10 résultats.
In[061]
is_member = arr_receipt['customer_id'].astype('<U1') != 'Z'
unq_id, inv_id = np.unique(arr_receipt['customer_id'][is_member],
return_inverse=True)
amount_arr = np.bincount(inv_id, arr_receipt['amount'][is_member])
make_array(unq_id.size, customer_id=unq_id, amount=amount_arr,
amount_log10=np.log10(amount_arr + 1))[:10]
Out[061]
array([('CS001113000004', 1298., 3.11360915),
('CS001114000005', 626., 2.79726754),
('CS001115000010', 3044., 3.4835873 ),
('CS001205000004', 1988., 3.29863478),
('CS001205000006', 3337., 3.52348633),
('CS001211000025', 456., 2.6599162 ),
('CS001212000027', 448., 2.65224634),
('CS001212000031', 296., 2.47275645),
('CS001212000046', 228., 2.35983548),
('CS001212000070', 456., 2.6599162 )],
dtype=[('customer_id', '<U14'), ('amount', '<f8'), ('amount_log10', '<f8')])
P_062
P-062: Le montant des ventes (montant) du bloc de données de détail du reçu (df_receipt) est totalisé pour chaque ID client (customer_id), et le montant total des ventes est converti en une valeur logarithmique naturelle (base = e) pour totaliser l'ID client et le montant des ventes. Afficher avec. Cependant, si l'ID client commence par "Z", il représente un non-membre, donc excluez-le du calcul. Vous pouvez afficher 10 résultats.
In[062]
is_member = arr_receipt['customer_id'].astype('<U1') != 'Z'
unq_id, inv_id = np.unique(arr_receipt['customer_id'][is_member],
return_inverse=True)
amount_arr = np.bincount(inv_id, arr_receipt['amount'][is_member])
make_array(unq_id.size, customer_id=unq_id, amount=amount_arr,
amount_log10=np.log1p(amount_arr))[:10]
Out[062]
array([('CS001113000004', 1298., 7.16935002),
('CS001114000005', 626., 6.44094654),
('CS001115000010', 3044., 8.02125618),
('CS001205000004', 1988., 7.59538728),
('CS001205000006', 3337., 8.1131271 ),
('CS001211000025', 456., 6.12468339),
('CS001212000027', 448., 6.10702289),
('CS001212000031', 296., 5.69373214),
('CS001212000046', 228., 5.433722 ),
('CS001212000070', 456., 6.12468339)],
dtype=[('customer_id', '<U14'), ('amount', '<f8'), ('amount_log10', '<f8')])
Recommended Posts