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

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

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 dem strukturierten Array von NumPy verarbeiten.

: arrow_backward: Vorheriger Artikel (# 1) : arrow_forward: Nächster Artikel (# 3)

Einführung

Lösen Sie als Studie des strukturierten Arrays von NumPy das Python-Problem von Data Science 100 Knock (Strukturierte Datenverarbeitung). Ich werde gehen.

Viele Leute, die in 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. Es ist eine Richtlinie, Funktionen nicht mit "np.vectorize ()" oder "np.frompyfunc ()" zu vektorisieren.

Dieses Mal werde ich die 10. bis 16. Frage stellen. Es scheint das Thema des bedingten Index von Zeichenketten zu sein. Die Ausgangsdaten wurden wie folgt gelesen (Datentypspezifikation wird vorerst verschoben).

import numpy as np
import pandas as pd

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

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

P_010

P-010: Extrahieren Sie aus dem Speicherdatenrahmen (df_store) alle Artikel, deren Speichercode (store_cd) mit "S14" beginnt, und zeigen Sie nur 10 Artikel an.

Verwenden Sie "np.char.startswith ()", um festzustellen, ob die Anfänge der Zeichenfolgen übereinstimmen. Geben Sie dem ersten Argument ein Array von Zeichenfolgen und dem zweiten Argument das zu suchende Wort.

In[010]


arr_store[np.char.startswith(arr_store['store_cd'], 'S14')][:10]

Es ist einfach, eine Funktion wie "np.char.xxx ()" zu verwenden, aber ich bin nicht gut in stringbezogenen Operationen in NumPy. Wenn Sie also * Geschwindigkeit * möchten, ist es besser, den Python-Standard für die Schleife zu verwenden. Oft gibt es Zeiten. In diesem Fall ist es schneller, wenn Sie das NumPy-Array in eine Liste konvertieren.

In[010]


arr_store[[item[:3] == 'S14'
           for item in arr_store['store_cd'].tolist()]][:10]

Wenn Sie nur die ersten Buchstaben sehen möchten, gibt es eine einfachere und schnellere Möglichkeit, dies zu tun. Wenn Sie die Spalte Store Code (store_cd) überprüfen,

arr_store['store_cd']
# array(['S12014', 'S13002', 'S14010', 'S14033', 'S14036', 'S13051',
#        ...
#        'S13003', 'S12053', 'S13037', 'S14024', 'S14006'], dtype='<U6')

Sie können sehen, dass sie alle aus 6-stelligen Zeichenfolgen bestehen. Alles, was Sie brauchen, sind die ersten 3 Zeichen. Lesen Sie sie daher erneut mit dem Datentyp "U3". Dann werden das 4. und die nachfolgenden Zeichen nicht gelesen und wie unten gezeigt verworfen.

arr_store['store_cd'].astype('<U3')
# array(['S12', 'S13', 'S14', 'S14', 'S14', 'S13', 'S13', 'S14', 'S13',
#        ...
#        'S14', 'S13', 'S12', 'S13', 'S12', 'S13', 'S14', 'S14'],
#       dtype='<U3')

Dies sollte den aus "S14" herausziehen, daher lautet die Antwort:

In[010]


arr_store[arr_store['store_cd'].astype('<U3') == 'S14'][:10]

Die Ausgabe ist wie folgt.

Out[010]


array([('S14010', 'Kikuna-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市港北区菊名一丁目', 'Ken Kanagawa Ken Yokohama Hokukukikunaichoume', '045-123-4032', 139.6326, 35.50049, 1732.),
       ('S14033', 'Akuwa-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市瀬谷区阿久和西一丁目', 'Ken Kanagawa Yokohama Shiseyaku Akwanishi Itchoume', '045-123-4043', 139.4961, 35.45918, 1495.),
       ('S14036', 'Sagamihara Central Store', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa相模原市中央二丁目', 'Kanagawa Kensagami Harashichu Ounichoume', '042-123-4045', 139.3716, 35.57327, 1679.),
       ('S14040', 'Nagatsuda-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市緑区長津田みなみ台五丁目', 'Ken Kanagawa Ken Yokohama Shimidori Kunagatsu Taminami Daigochoume', '045-123-4046', 139.4994, 35.52398, 1548.),
       ('S14050', 'Akuwa Nishi Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市瀬谷区阿久和西一丁目', 'Ken Kanagawa Yokohama Shiseyaku Akwanishi Itchoume', '045-123-4053', 139.4961, 35.45918, 1830.),
       ('S14028', 'Futatsubashi-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市瀬谷区二ツ橋町', 'Ken Kanagawa Yokohama Shiseyaku Futatsubashicho', '045-123-4042', 139.4963, 35.46304, 1574.),
       ('S14012', 'Honmoku Wada Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市中区本牧和田', 'Ken Kanagawa Yokohama Shinakakuhonmokuwada', '045-123-4034', 139.6582, 35.42156, 1341.),
       ('S14046', 'Kitayamada-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市都筑区北山田一丁目', 'Ken Kanagawa Yokohama Shitsuzuki Kukitayama Taichoume', '045-123-4049', 139.5916, 35.56189,  831.),
       ('S14022', 'Zushi-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa逗子市逗子一丁目', 'Kanagawa Kenzushizushiichoume', '046-123-4036', 139.5789, 35.29642, 1838.),
       ('S14011', 'Hiyoshi Honmachi Geschäft', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市港北区日吉本町四丁目', 'Ken Kanagawa Ken Yokohama Hokuhoku Hiyoshi Hongcho Yonchome', '045-123-4033', 139.6316, 35.54655,  890.)],
      dtype=[('store_cd', '<U6'), ('store_name', '<U6'), ('prefecture_cd', '<i4'), ('prefecture', '<U4'), ('address', '<U19'), ('address_kana', '<U30'), ('tel_no', '<U12'), ('longitude', '<f8'), ('latitude', '<f8'), ('floor_area', '<f8')])

Vergleichen wir die Geschwindigkeiten auf verschiedene Arten.

Time[010]


#Musterantwort
%timeit df_store.query("store_cd.str.startswith('S14')", engine='python').head(10)
# 3.46 ms ± 23.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

#Andere Arten von Pandas
%timeit df_store[df_store['store_cd'].str.startswith('S14')][:10]
# 876 µs ± 18.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df_store.loc[[index for index, item in enumerate(df_store['store_cd']) if item[:3] == 'S14']][:10]
# 732 µs ± 17.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

#Methode mit NumPy
%timeit arr_store[np.char.startswith(arr_store['store_cd'], 'S14')][:10]
# 54.3 µs ± 3.17 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit arr_store[[item[:3] == 'S14' for item in arr_store['store_cd'].tolist()]][:10]
# 22.8 µs ± 377 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit arr_store[arr_store['store_cd'].astype('<U3') == 'S14'][:10]
# 5.55 µs ± 91.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

String-bedingte Indizes, die pd.DataFrame.query () verwenden, sind bekannt dafür, dass sie langsam sind.

P_011

P-011: Extrahieren Sie alle Artikel aus dem Kundendatenrahmen (df_customer) mit nur einer Kunden-ID (customer_id), die auf 1 endet, und zeigen Sie nur 10 Artikel an.

Es ist das gleiche wie bei der vorherigen Frage. Verwenden Sie die Funktion np.char.endswith ().

In[011]


arr_customer[np.char.endswith(arr_customer['customer_id'], '1')][:10]

Wenn Sie sich Gedanken über die Geschwindigkeit machen, verwenden Sie die for-Schleife.

In[011]


arr_customer[[item[-1] == '1'
              for item in arr_customer['customer_id']]][:10]

Denken Sie an einen schnelleren Weg. Sie können die Taktik .astype () nicht verwenden, um das letzte Zeichen in einer Zeichenfolge anzuzeigen. In diesem Beispiel ist es jedoch möglich, eine Hochgeschwindigkeitsverarbeitung auf eine andere Weise durchzuführen. Wenn Sie die Spalte Kunden-ID (customer_id) überprüfen,

arr_customer['customer_id']
# array(['CS021313000114', 'CS037613000071', 'CS031415000172', ...,
#        'CS012403000043', 'CS033512000184', 'CS009213000022'], dtype='<U14')

Sie können sehen, dass ** alle Zeilen die gleiche Anzahl von Zeichen ** haben (14 Ziffern). Sie müssen nur nach dem mit "1" am Ende suchen. Dazu konvertieren Sie zuerst das Array "arr_customer [" customer_id "] mit der Methode" .tobytes () "in eine Zeichenfolge von Bytes und konvertieren dann dieses Array, das mit dem Datentyp" U14 "gelesen wurde, in" Lesen Sie den Datentyp "U1" erneut mit der Funktion "np.frombuffer ()". Wenn es mit der Methode "reshape ()" weiter in ein 14-Spalten-Array umgeordnet wird, sieht es wie folgt aus.

#Teilen Sie alle Kunden-ID-Daten in Zeichen auf
np.frombuffer(arr_customer['customer_id'].tobytes(), dtype='<U1')
# array(['C', 'S', '0', ..., '0', '2', '2'], dtype='<U1')

#Kehren Sie zu 14 Zeichen pro Zeile zurück
np.frombuffer(arr_customer['customer_id'].tobytes(), dtype='<U1').reshape(len(arr_customer), -1)
# array([['C', 'S', '0', ..., '1', '1', '4'],
#        ['C', 'S', '0', ..., '0', '7', '1'],
#        ...,
#        ['C', 'S', '0', ..., '1', '8', '4'],
#        ['C', 'S', '0', ..., '0', '2', '2']], dtype='<U1')

Da die von der "Zeile, deren letzte Spalte" 1 "ist, in diesem Array benötigte Zeile wie folgt lautet. Diese Technik ist durchaus anwendbar.

In[011]


arr_customer[np.frombuffer(arr_customer['customer_id'].tobytes(), dtype='<U1')
             .reshape(len(arr_customer), -1)[:, -1]
             == '1'][:10]

Die Ausgabe ist wie folgt.

Out[011]


array([('CS037613000071', 'Masahiko Hexagon', 9, 'Unbekannt', '1952-04-01', 66, '136-0076', 'Minamisago, Koto-ku, Tokio**********', 'S13037', 20150414, '0-00000000-0'),
       ('CS028811000001', 'Kaori Horii', 1, 'Weiblich', '1933-03-27', 86, '245-0016', 'Izumi-cho, Izumi-ku, Yokohama-shi, Kanagawa**********', 'S14028', 20160115, '0-00000000-0'),
       ('CS040412000191', 'Ikue Kawai', 1, 'Weiblich', '1977-01-05', 42, '226-0021', 'Kitahachisakucho, Midori-ku, Yokohama-shi, Kanagawa**********', 'S14040', 20151101, '1-20091025-4'),
       ('CS028314000011', 'Aoi Kosuga', 1, 'Weiblich', '1983-11-26', 35, '246-0038', 'Miyazawa, Setani-ku, Yokohama-shi, Kanagawa**********', 'S14028', 20151123, '1-20080426-5'),
       ('CS039212000051', 'Erika Fujishima', 1, 'Weiblich', '1997-02-03', 22, '166-0001', 'Asaya Kita, Suginami-ku, Tokio**********', 'S13039', 20171121, '1-20100215-4'),
       ('CS015412000111', 'Natsuki Matsui', 1, 'Weiblich', '1972-10-04', 46, '136-0071', 'Kamedo, Koto-ku, Tokio**********', 'S13015', 20150629, '0-00000000-0'),
       ('CS004702000041', 'Hiroshi Nojima', 0, 'männlich', '1943-08-24', 75, '176-0022', 'Mukaiyama, Nerima-ku, Tokio**********', 'S13004', 20170218, '0-00000000-0'),
       ('CS041515000001', 'Chinatsu Kurita', 1, 'Weiblich', '1967-01-02', 52, '206-0001', 'Wada, Tama City, Tokio**********', 'S13041', 20160422, 'E-20100803-F'),
       ('CS029313000221', 'Hikari Hojo', 1, 'Weiblich', '1987-06-19', 31, '279-0011', 'Mihama, Stadt Urayasu, Präfektur Chiba**********', 'S12029', 20180810, '0-00000000-0'),
       ('CS034312000071', 'Nao Mochizuki', 1, 'Weiblich', '1980-09-20', 38, '213-0026', 'Kusue, Takatsu-ku, Kawasaki-shi, Kanagawa**********', 'S14034', 20160106, '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')])

Vergleichen wir die Geschwindigkeiten.

Time[011]


%timeit df_customer.query("customer_id.str.endswith('1')", engine='python').head(10)
# 12.2 ms ± 454 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit arr_customer[np.char.endswith(arr_customer['customer_id'], '1')][:10]
# 20.7 ms ± 847 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit arr_customer[[item[-1] == '1' for item in arr_customer['customer_id']]][:10]
# 9.44 ms ± 185 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit arr_customer[np.frombuffer(arr_customer['customer_id'].tobytes(), dtype='<U1').reshape(len(arr_customer), -1)[:, -1] == '1'][:10]
# 1.83 ms ± 77 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

np.char.xxx () scheint in einigen Fällen langsamer zu sein alspd.query ()...

P_012

P-012: Alle Artikel aus dem Geschäftsdatenrahmen (df_store) nur für Geschäfte in Yokohama anzeigen.

In[012]


arr_store[np.char.find(arr_store['address'], 'Yokohama') >= 0]

Oder

In[012]


arr_store[['Yokohama' in item
           for item in arr_store['address'].tolist()]]

Die Anzahl der Zeichen im Adressfeld ist unbestimmt, aber "Yokohama City" wird immer im 5., 6. und 7. Zeichen angezeigt. Nach dem Ausschneiden auf nur die ersten 7 Zeichen mit ".astype (" <U7 ")" werden nur die letzten 3 Zeichen angezeigt Machen Sie ein Array von

In[012]


arr_store[np.frombuffer(arr_store['address'].astype('<U7').view('<U1')
                        .reshape(len(arr_store), -1)[:, 4:].tobytes(),
                        dtype='<U3')
          == 'Yokohama']

Du kannst auch.

Out[012]


array([('S14010', 'Kikuna-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市港北区菊名一丁目', 'Ken Kanagawa Ken Yokohama Hokukukikunaichoume', '045-123-4032', 139.6326, 35.50049, 1732.),
       ('S14033', 'Akuwa-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市瀬谷区阿久和西一丁目', 'Ken Kanagawa Yokohama Shiseyaku Akwanishi Itchoume', '045-123-4043', 139.4961, 35.45918, 1495.),
       ('S14040', 'Nagatsuda-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市緑区長津田みなみ台五丁目', 'Ken Kanagawa Ken Yokohama Shimidori Kunagatsu Taminami Daigochoume', '045-123-4046', 139.4994, 35.52398, 1548.),
       ('S14050', 'Akuwa Nishi Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市瀬谷区阿久和西一丁目', 'Ken Kanagawa Yokohama Shiseyaku Akwanishi Itchoume', '045-123-4053', 139.4961, 35.45918, 1830.),
       ('S14028', 'Futatsubashi-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市瀬谷区二ツ橋町', 'Ken Kanagawa Yokohama Shiseyaku Futatsubashicho', '045-123-4042', 139.4963, 35.46304, 1574.),
       ('S14012', 'Honmoku Wada Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市中区本牧和田', 'Ken Kanagawa Yokohama Shinakakuhonmokuwada', '045-123-4034', 139.6582, 35.42156, 1341.),
       ('S14046', 'Kitayamada-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市都筑区北山田一丁目', 'Ken Kanagawa Yokohama Shitsuzuki Kukitayama Taichoume', '045-123-4049', 139.5916, 35.56189,  831.),
       ('S14011', 'Hiyoshi Honmachi Geschäft', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市港北区日吉本町四丁目', 'Ken Kanagawa Ken Yokohama Hokuhoku Hiyoshi Hongcho Yonchome', '045-123-4033', 139.6316, 35.54655,  890.),
       ('S14048', 'Nakagawa Chuo Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市都筑区中川中央二丁目', 'Ken Kanagawa Ken Yokohama Shitsuzuki Kunakagawa Chuo Unichome', '045-123-4051', 139.5758, 35.54912, 1657.),
       ('S14042', 'Shin Yamashita Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市中区新山下二丁目', 'Ken Kanagawa Yokohama Shinakakushin Yamashitani Chome', '045-123-4047', 139.6593, 35.43894, 1044.),
       ('S14006', 'Kuzugaya Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市都筑区葛が谷', 'Ken Kanagawa Yokohama Shitsuzuki Kuzugaya', '045-123-4031', 139.5633, 35.53573, 1886.)],
      dtype=[('store_cd', '<U6'), ('store_name', '<U6'), ('prefecture_cd', '<i4'), ('prefecture', '<U4'), ('address', '<U19'), ('address_kana', '<U30'), ('tel_no', '<U12'), ('longitude', '<f8'), ('latitude', '<f8'), ('floor_area', '<f8')])

P_013

P-013: Extrahieren Sie aus dem Kundendatenrahmen (df_customer) alle Daten, deren Statuscode (status_cd) mit dem Alphabet A bis F beginnt, und zeigen Sie nur 10 Elemente an.

Das ist mühsam. In der Modellantwort suchen wir nach regulären Ausdrücken, aber vorerst werden wir dies ohne Verwendung regulärer Ausdrücke tun. Wenn Sie mit np.char.startswith () gehen, wird es so sein.

In[013]


arr_customer[
    np.char.startswith(arr_customer['status_cd'],
                       np.array(list('ABCDEF'))[:, None])
    .any(0)][:10]

Es fühlt sich ziemlich hart an. Es ist einfacher zu bedienen.

In[013]


arr_customer[[item[0] in set('ABCDEF')
              for item in arr_customer['status_cd'].tolist()]][:10]

Lesen Sie nur den Anfang des Strings und np.in1d (). Es ist schnell und einfach.

In[013]


arr_customer[np.in1d(arr_customer['status_cd'].astype('<U1'),
                     np.fromiter('ABCDEF', dtype='<U1'))][:10]

Das Suchwort ist hier übrigens auch ein NumPy-Array, aber die Geschwindigkeit hat sich auch mit list ('ABCDEF') nicht wesentlich geändert.

Out[013]


array([('CS031415000172', 'Kimiko Utada', 1, 'Weiblich', '1976-10-04', 42, '151-0053', 'Yoyogi, Shibuya-ku, Tokio**********', 'S13031', 20150529, 'D-20100325-C'),
       ('CS015414000103', 'Yoko Okuno', 1, 'Weiblich', '1977-08-09', 41, '136-0073', 'Kitasa, Koto-ku, Tokio**********', 'S13015', 20150722, 'B-20100609-B'),
       ('CS011215000048', 'Saya Ashida', 1, 'Weiblich', '1992-02-01', 27, '223-0062', 'Hiyoshi Honmachi, Kohoku-ku, Yokohama-shi, Kanagawa**********', 'S14011', 20150228, 'C-20100421-9'),
       ('CS029415000023', 'Riho Umeda', 1, 'Weiblich', '1976-01-17', 43, '279-0043', 'Fujimi, Stadt Urayasu, Präfektur Chiba**********', 'S12029', 20150610, 'D-20100918-E'),
       ('CS035415000029', 'Maki Terazawa', 9, 'Unbekannt', '1977-09-27', 41, '158-0096', 'Tamagawadai, Setagaya-ku, Tokio**********', 'S13035', 20141220, 'F-20101029-F'),
       ('CS031415000106', 'Yumiko Uno', 1, 'Weiblich', '1970-02-26', 49, '151-0053', 'Yoyogi, Shibuya-ku, Tokio**********', 'S13031', 20150201, 'F-20100511-E'),
       ('CS029215000025', 'Miho Ishikura', 1, 'Weiblich', '1993-09-28', 25, '279-0022', 'Imagawa, Stadt Urayasu, Präfektur Chiba**********', 'S12029', 20150708, 'B-20100820-C'),
       ('CS033605000005', 'Yuta Inomata', 0, 'männlich', '1955-12-05', 63, '246-0031', 'Setani, Setani-ku, Yokohama-shi, Kanagawa**********', 'S14033', 20150425, 'F-20100917-E'),
       ('CS033415000229', 'Nanami Itagaki', 1, 'Weiblich', '1977-11-07', 41, '246-0021', 'Stadt Futatsuhashi, Gemeinde Setani, Stadt Yokohama, Präfektur Kanagawa**********', 'S14033', 20150712, 'F-20100326-E'),
       ('CS008415000145', 'Mao Kuroya', 1, 'Weiblich', '1977-06-27', 41, '157-0067', 'Kitami, Setagaya-ku, Tokio**********', 'S13008', 20150829, 'F-20100622-F')],
      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_014

P-014: Extrahieren Sie aus dem Kundendatenrahmen (df_customer) alle Daten, deren Statuscode (status_cd) mit den Nummern 1 bis 9 endet, und zeigen Sie nur 10 Elemente an.

In[014]


arr_customer[[item[-1] in set('123456789')
              for item in arr_customer['status_cd'].tolist()]][:10]

In[014]


arr_customer[np.in1d(np.frombuffer(arr_customer['status_cd'].tobytes(),
                                   dtype='<U1')
                     .reshape(len(arr_customer), -1)[:, -1],
                     np.fromiter('123456789', dtype='<U1'))][:10]

Out[014]


array([('CS001215000145', 'Miki Tazaki', 1, 'Weiblich', '1995-03-29', 24, '144-0055', 'Nakarokugo, Ota-ku, Tokio**********', 'S13001', 20170605, '6-20090929-2'),
       ('CS033513000180', 'Haruka Anzai', 1, 'Weiblich', '1962-07-11', 56, '241-0823', 'Zenbe-cho, Asahi-ku, Yokohama-shi, Kanagawa**********', 'S14033', 20150728, '6-20080506-5'),
       ('CS011215000048', 'Saya Ashida', 1, 'Weiblich', '1992-02-01', 27, '223-0062', 'Hiyoshi Honmachi, Kohoku-ku, Yokohama-shi, Kanagawa**********', 'S14011', 20150228, 'C-20100421-9'),
       ('CS040412000191', 'Ikue Kawai', 1, 'Weiblich', '1977-01-05', 42, '226-0021', 'Kitahachisakucho, Midori-ku, Yokohama-shi, Kanagawa**********', 'S14040', 20151101, '1-20091025-4'),
       ('CS009315000023', 'Fumiyo Minagawa', 1, 'Weiblich', '1980-04-15', 38, '154-0012', 'Komazawa, Setagaya-ku, Tokio**********', 'S13009', 20150319, '5-20080322-1'),
       ('CS015315000033', 'Fukushi Rinako', 1, 'Weiblich', '1983-03-17', 36, '135-0043', 'Shiohama, Koto-ku, Tokio**********', 'S13015', 20141024, '4-20080219-3'),
       ('CS023513000066', 'Kobe Sora', 1, 'Weiblich', '1961-12-17', 57, '210-0005', 'Stadt Higashida, Gemeinde Kawasaki, Stadt Kawasaki, Präfektur Kanagawa**********', 'S14023', 20150915, '5-20100524-9'),
       ('CS035513000134', 'Miho Ichikawa', 1, 'Weiblich', '1960-03-27', 59, '156-0053', 'Sakura, Setagaya-ku, Tokio**********', 'S13035', 20150227, '8-20100711-9'),
       ('CS001515000263', 'Takamatsu Sommerhimmel', 1, 'Weiblich', '1962-11-09', 56, '144-0051', 'Nishi Kamata, Ota-ku, Tokio**********', 'S13001', 20160812, '1-20100804-1'),
       ('CS040314000027', 'Kimiro Tsuruta', 9, 'Unbekannt', '1986-03-26', 33, '226-0027', 'Nagatsuda, Midori-ku, Stadt Yokohama, Präfektur Kanagawa**********', 'S14040', 20150122, '2-20080426-4')],
      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_015

P-015: Extrahieren Sie aus dem Kundendatenrahmen (df_customer) alle Daten, deren Statuscode (status_cd) mit den Buchstaben A bis F beginnt und mit den Zahlen 1 bis 9 endet, und zeigen Sie nur 10 Elemente an. ..

Selbst wenn es mehrere Bedingungen gibt, können Sie diese problemlos mit der for-Schleife abrufen.

In[015]


arr_customer[[item[0] in set('ABCDEF') and item[-1] in set('123456789')
              for item in arr_customer['status_cd'].tolist()]][:10]

Die Methode zum Schneiden einer Zeichenfolge und zum Verwenden von "np.in1d ()" hat viele Bedingungen und ist beim Schreiben schwierig geworden. Niemand würde sich die Mühe machen, Code wie diesen zu schreiben: (Gibt es einen besseren Weg ...?)

In[015]


statud_cd_split = np.frombuffer(arr_customer['status_cd'].tobytes(),
                                dtype='<U1').reshape(len(arr_customer), -1)
arr_customer[np.in1d(statud_cd_split[:, 0],
                     np.fromiter('ABCDEF', dtype='<U1'))
             &
             np.in1d(statud_cd_split[:, -1],
                     np.fromiter('123456789', dtype='<U1'))][:10]

Out[015]


array([('CS011215000048', 'Saya Ashida', 1, 'Weiblich', '1992-02-01', 27, '223-0062', 'Hiyoshi Honmachi, Kohoku-ku, Yokohama-shi, Kanagawa**********', 'S14011', 20150228, 'C-20100421-9'),
       ('CS022513000105', 'Kimiko Shimamura', 1, 'Weiblich', '1962-03-12', 57, '249-0002', 'Yamane, Zushi City, Präfektur Kanagawa**********', 'S14022', 20150320, 'A-20091115-7'),
       ('CS001515000096', 'Yoko Mizuno', 9, 'Unbekannt', '1960-11-29', 58, '144-0053', 'Kamata Honmachi, Ota-ku, Tokio**********', 'S13001', 20150614, 'A-20100724-7'),
       ('CS013615000053', 'Kiyo Nishiwaki', 1, 'Weiblich', '1953-10-18', 65, '261-0026', 'Makuhari Nishi, Mihama-ku, Chiba-shi, Chiba**********', 'S12013', 20150128, 'B-20100329-6'),
       ('CS020412000161', 'Kaoru Komiya', 1, 'Weiblich', '1974-05-21', 44, '174-0042', 'Higashisakashita, Itabashi-ku, Tokio**********', 'S13020', 20150822, 'B-20081021-3'),
       ('CS001215000097', 'Asami Takenaka', 1, 'Weiblich', '1990-07-25', 28, '146-0095', 'Tamagawa, Ota-ku, Tokio**********', 'S13001', 20170315, 'A-20100211-2'),
       ('CS035212000007', 'Erika Uchimura', 1, 'Weiblich', '1990-12-04', 28, '152-0023', 'Yakumo, Meguro-ku, Tokio**********', 'S13035', 20151013, 'B-20101018-6'),
       ('CS002515000386', 'Kou Noda', 1, 'Weiblich', '1963-05-30', 55, '185-0013', 'Nishikoigakubo, Stadt Kokubunji, Tokio**********', 'S13002', 20160410, 'C-20100127-8'),
       ('CS001615000372', 'Inagaki Suzuka', 1, 'Weiblich', '1956-10-29', 62, '144-0035', 'Minami Kamata, Ota-ku, Tokio**********', 'S13001', 20170403, 'A-20100104-1'),
       ('CS032512000121', 'Tomoyo Matsui', 1, 'Weiblich', '1962-09-04', 56, '210-0011', 'Fujimi, Kawasaki-ku, Kawasaki-shi, Kanagawa**********', 'S13032', 20150727, 'A-20100103-5')],
      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')])

Das Schreiben ist mühsam, aber schneller als eine for-Schleife.

Time[015]


%timeit df_customer.query("status_cd.str.contains('^[A-F].*[1-9]$', regex=True)", engine='python').head(10)
# 31 ms ± 1.25 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit arr_customer[[item[0] in set('ABCDEF') and item[-1] in set('123456789') for item in arr_customer['status_cd'].tolist()]][:10]
# 16.7 ms ± 1.37 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
statud_cd_split = np.frombuffer(arr_customer['status_cd'].tobytes(), dtype='<U1').reshape(len(arr_customer), -1)
arr_customer[np.in1d(statud_cd_split[:, 0], np.fromiter('ABCDEF', dtype='<U1'))
             & np.in1d(statud_cd_split[:, -1], np.fromiter('123456789', dtype='<U1'))][:10]
# 3.94 ms ± 17.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

P_016

P-016: Zeigen Sie im Speicherdatenrahmen (df_store) alle Elemente mit 3 Ziffern - 3 Ziffern - 4 Ziffern für die Telefonnummer (tel_no) an.

Sollte ich an dieser Stelle das reguläre Ausdrucksmodul "re" verwenden?

In[016]


import re

arr_store[[bool(re.fullmatch(r'[0-9]{3}-[0-9]{3}-[0-9]{4}', item))
           for item in arr_store['tel_no'].tolist()]]

In diesem Fall gab es bei Betrachtung der Daten nur 10-stellige Telefonnummern und keine fehlerhaften Werte, sodass wir sie durch das Problem "Zeilen mit dem 4. und 8. Zeichen" - "" ersetzen konnten. Es war. Eine der Lösungen besteht darin, das Problem anhand der Daten flexibel zu lesen.

In[016]


tel_no_split = np.frombuffer(arr_store['tel_no'].tobytes(),
                             dtype='<U1').reshape(len(arr_store), -1)
arr_store[(tel_no_split[:, 3] == '-') & (tel_no_split[:, 7] == '-')]

Out[016]


array([('S12014', 'Chigusadai-Laden', 12, 'Präfektur Chiba', 'Präfektur Chiba千葉市稲毛区千草台一丁目', 'Cibaken Chibashi Inagekuchigusadai Itchoume', '043-123-4003', 140.118 , 35.63559, 1698.),
       ('S13002', 'Kokubunji-Laden', 13, 'Tokio', 'Tokio国分寺市本多二丁目', 'Tokio Tokoku Bunji Shihondani Choume', '042-123-4008', 139.4802, 35.70566, 1735.),
       ('S14010', 'Kikuna-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市港北区菊名一丁目', 'Ken Kanagawa Ken Yokohama Hokukukikunaichoume', '045-123-4032', 139.6326, 35.50049, 1732.),
       ('S14033', 'Akuwa-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市瀬谷区阿久和西一丁目', 'Ken Kanagawa Yokohama Shiseyaku Akwanishi Itchoume', '045-123-4043', 139.4961, 35.45918, 1495.),
       ('S14036', 'Sagamihara Central Store', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa相模原市中央二丁目', 'Kanagawa Kensagami Harashichu Ounichoume', '042-123-4045', 139.3716, 35.57327, 1679.),
       ('S14040', 'Nagatsuda-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市緑区長津田みなみ台五丁目', 'Ken Kanagawa Ken Yokohama Shimidori Kunagatsu Taminami Daigochoume', '045-123-4046', 139.4994, 35.52398, 1548.),
       ('S14050', 'Akuwa Nishi Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市瀬谷区阿久和西一丁目', 'Ken Kanagawa Yokohama Shiseyaku Akwanishi Itchoume', '045-123-4053', 139.4961, 35.45918, 1830.),
       ('S13052', 'Morino-Laden', 13, 'Tokio', 'Tokio町田市森野三丁目', 'Tokio Tomachida Shimorino Sanchoume', '042-123-4030', 139.4383, 35.55293, 1087.),
       ('S14028', 'Futatsubashi-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市瀬谷区二ツ橋町', 'Ken Kanagawa Yokohama Shiseyaku Futatsubashicho', '045-123-4042', 139.4963, 35.46304, 1574.),
       ('S14012', 'Honmoku Wada Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市中区本牧和田', 'Ken Kanagawa Yokohama Shinakakuhonmokuwada', '045-123-4034', 139.6582, 35.42156, 1341.),
       ('S14046', 'Kitayamada-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市都筑区北山田一丁目', 'Ken Kanagawa Yokohama Shitsuzuki Kukitayama Taichoume', '045-123-4049', 139.5916, 35.56189,  831.),
       ('S14022', 'Zushi-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa逗子市逗子一丁目', 'Kanagawa Kenzushizushiichoume', '046-123-4036', 139.5789, 35.29642, 1838.),
       ('S14011', 'Hiyoshi Honmachi Geschäft', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市港北区日吉本町四丁目', 'Ken Kanagawa Ken Yokohama Hokuhoku Hiyoshi Hongcho Yonchome', '045-123-4033', 139.6316, 35.54655,  890.),
       ('S13016', 'Koganei-Laden', 13, 'Tokio', 'Tokio小金井市本町一丁目', 'Tokio Tokoganei Shihoncho Ichoume', '042-123-4015', 139.5094, 35.70018, 1399.),
       ('S14034', 'Kawasaki Nogawa Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa川崎市宮前区野川', 'Kanagawa Kenkawa Sakimiyama Ekunogawa', '044-123-4044', 139.5998, 35.57693, 1318.),
       ('S14048', 'Nakagawa Chuo Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市都筑区中川中央二丁目', 'Ken Kanagawa Ken Yokohama Shitsuzuki Kunakagawa Chuo Unichome', '045-123-4051', 139.5758, 35.54912, 1657.),
       ('S12007', 'Sakura-Laden', 12, 'Präfektur Chiba', 'Präfektur Chiba佐倉市上志津', 'Cibaken Sakura Shikamishizu', '043-123-4001', 140.1452, 35.71872, 1895.),
       ('S14026', 'Tsujido West Coast Store', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa藤沢市辻堂西海岸二丁目', 'Kanagawa Ken Fujisawa Shitsuji Dounishi Kaigan Nichome', '046-123-4040', 139.4466, 35.32464, 1732.),
       ('S13041', 'Hachioji-Laden', 13, 'Tokio', 'Tokio八王子市大塚', 'Tokio Hachioujishio Otsuka', '042-123-4026', 139.4235, 35.63787,  810.),
       ('S14049', 'Kawasaki Daishi Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa川崎市川崎区中瀬三丁目', 'Kanagawa Kenkawa Saki Kawasaki Kunakaze Sanchoume', '044-123-4052', 139.7327, 35.53759,  962.),
       ('S14023', 'Kawasaki-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa川崎市川崎区本町二丁目', 'Kanagawa Kenkawa Saki Kawasaki Kuhoncho Nichome', '044-123-4037', 139.7028, 35.53599, 1804.),
       ('S13018', 'Kiyose-Laden', 13, 'Tokio', 'Tokio清瀬市松山一丁目', 'Tokio Tokiyoshi Matsuyamai', '042-123-4017', 139.5178, 35.76885, 1220.),
       ('S14027', 'Minami Fujisawa Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa藤沢市南藤沢', 'Kanagawa Ken Fujisawa Shiminami Fujisawa', '046-123-4041', 139.4896, 35.33762, 1521.),
       ('S14021', 'Isehara-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa伊勢原市伊勢原四丁目', 'Ken Kanagawa Isehara Shiisehara Yonchoume', '046-123-4035', 139.3129, 35.40169,  962.),
       ('S14047', 'Sagamihara-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa相模原市千代田六丁目', 'Kanagawa Kensagami Harashi Chiyodarokuchoume', '042-123-4050', 139.3748, 35.55959, 1047.),
       ('S12013', 'Narashino Laden', 12, 'Präfektur Chiba', 'Präfektur Chiba習志野市芝園一丁目', 'Ciba Kennarashi kein Shishi Bazono Ichoume', '047-123-4002', 140.022 , 35.66122,  808.),
       ('S14042', 'Shin Yamashita Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市中区新山下二丁目', 'Ken Kanagawa Yokohama Shinakakushin Yamashitani Chome', '045-123-4047', 139.6593, 35.43894, 1044.),
       ('S12030', 'Yawata-Laden', 12, 'Präfektur Chiba', 'Präfektur Chiba市川市八幡三丁目', 'Cibaken Ichikawa Shiyawata Sanchoume', '047-123-4005', 139.924 , 35.72318, 1162.),
       ('S14025', 'Yamato-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa大和市下和田', 'Ken Kanagawa Yamatoshi Shimowada', '046-123-4039', 139.468 , 35.43414, 1011.),
       ('S14045', 'Atsugi-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa厚木市中町二丁目', 'Kanagawaken Atsugi Shinakacho Nichoume', '046-123-4048', 139.3651, 35.44182,  980.),
       ('S12029', 'Higashino-Laden', 12, 'Präfektur Chiba', 'Präfektur Chiba浦安市東野一丁目', 'Cibaken Urayasushi Higashino Itchoume', '047-123-4004', 139.8968, 35.65086, 1101.),
       ('S12053', 'Takasu-Laden', 12, 'Präfektur Chiba', 'Präfektur Chiba浦安市高洲五丁目', 'Cibaken Urayasushitakasugochome', '047-123-4006', 139.9176, 35.63755, 1555.),
       ('S14024', 'Mita-Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa川崎市多摩区三田四丁目', 'Kanagawa Kenkawa Saxita Makumaitayon Chome', '044-123-4038', 139.5424, 35.6077 ,  972.),
       ('S14006', 'Kuzugaya Laden', 14, 'Präfektur Kanagawa', 'Präfektur Kanagawa横浜市都筑区葛が谷', 'Ken Kanagawa Yokohama Shitsuzuki Kuzugaya', '045-123-4031', 139.5633, 35.53573, 1886.)],
      dtype=[('store_cd', '<U6'), ('store_name', '<U6'), ('prefecture_cd', '<i4'), ('prefecture', '<U4'), ('address', '<U19'), ('address_kana', '<U30'), ('tel_no', '<U12'), ('longitude', '<f8'), ('latitude', '<f8'), ('floor_area', '<f8')])

Warum muss ich all dieses Problem ausgeben?

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