Как создать новый столбец, если текст из одного столбца, если текст из второго столбца содержит указанный c шаблон строки? - PullRequest
1 голос
/ 16 января 2020

Мои текущие данные выглядят примерно так

+-------+----------------------------+-------------------+-----------------------+
| Index |             0              |         1         |           2           |
+-------+----------------------------+-------------------+-----------------------+
|     0 | Reference Curr             | Daybook / Voucher | Invoice Date Due Date |
|     1 | V50011 Tech Comp           | nan               | Phone:0177222222      |
|     2 | Regis Place                | nan               | Fax:017757575789      |
|     3 | Catenberry                 | nan               | nan                   |
|     4 | Manhattan, NY              | nan               | nan                   |
|     5 | V7484 Pipe                 | nan               | Phone:                   |
|     6 | Japan                      | nan               | nan                   |
|     7 | nan                        | nan               | nan                   |
|     8 | 4543.34GBP (British Pound) | nan               | nan                   |
+-------+----------------------------+-------------------+-----------------------+

Я пытаюсь создать новый столбец df['Company'], который должен содержать то, что находится в df[0], если оно начинается с буквы "V" и если в df[2] есть «Телефон». Если условие не выполняется, то оно может быть nan. Ниже приведено то, что я ищу.

+-------+----------------------------+-------------------+-----------------------+------------+
| Index |             0              |         1         |           2           | Company    |
+-------+----------------------------+-------------------+-----------------------+------------+
|     0 | Reference Curr             | Daybook / Voucher | Invoice Date Due Date | nan        |
|     1 | V50011 Tech                | nan               | Phone:0177222222      |V50011 Tech |
|     2 | Regis Place                | nan               | Fax:017757575789      | nan        |
|     3 | Catenberry                 | nan               | nan                   | nan        |
|     4 | Manhattan, NY              | nan               | nan                   | nan        |
|     5 | V7484 Pipe                 | nan               | Phone:                | V7484 Pipe |
|     6 | Japan                      | nan               | nan                   | nan        |
|     7 | nan                        | nan               | nan                   | nan        |
|     8 | 4543.34GBP (British Pound) | nan               | nan                   | nan        |
+-------+----------------------------+-------------------+-----------------------+------------+

Я пробую приведенный ниже скрипт, но получаю ошибку ValueError: Wrong number of items passed 1420, размещение подразумевает 1

df['Company'] = pd.np.where(df[2].str.contains("Ph"), df[0].str.extract(r"(^V[A-Za-z0-9]+)"),"stop")

Я поставил "стоп" как часть else, потому что я не знаю, как позволить python использовать nan, когда условие не выполняется.

Я также хотел бы иметь возможность разобрать секцию df [0 ], например, только раздел v5001, но не остальное содержимое ячейки. Я попробовал что-то подобное, используя ответ AMC, но получил ошибку:

df.loc[df[0].str.startswith('V') & df[2].str.contains('Phone'), 'Company'] = df[0].str.extract(r"(^V[A-Za-z0-9]+)")

Спасибо

Ответы [ 5 ]

2 голосов
/ 16 января 2020

Вы не предоставили нам простой способ протестировать потенциальные решения, но это должно помочь:

df.loc[df[0].str.startswith('V') & df[2].str.contains('Phone'), 'Company'] = df[0]
2 голосов
/ 16 января 2020

Потенциальным решением этой проблемы было бы использование списка понимания. Вероятно, вы могли бы повысить скорость, используя некоторые из pandas 'встроенных функций, но это поможет вам.

#!/usr/bin/env python

import numpy as np
import pandas as pd

df = pd.DataFrame({
    0:["reference", "v5001 tech comp", "catenberry", "very different"],
    1:["not", "phone", "other", "text"]
    })

df["new_column"] = [x  if (x[0].lower() == "v") & ("phone" in y.lower())
  else np.nan for x,y in df.loc[:, [0,1]].values]

print(df)

, который будет производить

                 0      1       new_column
0        reference    not              NaN
1  v5001 tech comp  phone  v5001 tech comp
2       catenberry  other              NaN
3   very different   text              NaN

Все, что я делаю, это беру два ваших условия и создаю новый список, который затем будет назначен вашему новому столбцу.

1 голос
/ 16 января 2020

Вот еще один способ получить ваш результат

condition1=df['0'].str.startswith('V')
condition2=df['2'].str.contains('Phone')

df['Company']=np.where((condition1 & condition2), df['0'],np.nan)
df['Company']=df['Company'].str.split(' ',expand=True)
0 голосов
/ 16 января 2020

IIU C,

мы можем использовать либо логическое условие для извлечения V-номера с некоторым базовым c регулярным выражением,

, либо мы можем применить ту же формулу в где оператор.

, чтобы установить значение NaN, мы можем использовать np.nan

, если вы хотите получить всю строку после V, мы можем использовать [V]\w+.*, который будет захватывать все после первое совпадение.

from IO import StringIO

 d = """+-------+----------------------------+-------------------+-----------------------+
| Index |             0              |         1         |           2           |
+-------+----------------------------+-------------------+-----------------------+
|     0 | Reference Curr             | Daybook / Voucher | Invoice Date Due Date |
|     1 | V50011 Tech Comp           | nan               | Phone:0177222222      |
|     2 | Regis Place                | nan               | Fax:017757575789      |
|     3 | Catenberry                 | nan               | nan                   |
|     4 | Manhattan, NY              | nan               | nan                   |
|     5 | Ultilagro, CT              | nan               | nan                   |
|     6 | Japan                      | nan               | nan                   |
|     7 | nan                        | nan               | nan                   |
|     8 | 4543.34GBP (British Pound) | nan               | nan                   |
+-------+----------------------------+-------------------+-----------------------+"""

df = pd.read_csv(StringIO(d),sep='|',skiprows=1)
df = df.iloc[1:-1,2:-1]
df.columns = df.columns.str.strip()

df["3"] = df[df["2"].str.contains("phone", case=False) == True]["0"].str.extract(
    r"([V]\w+)"
)

print(df[['0','2','3']])
                           0                      2       3
1              Reference Curr  Invoice Date Due Date     nan
2            V50011 Tech Comp       Phone:0177222222  V50011
3                 Regis Place       Fax:017757575789     nan
4                  Catenberry                    nan     nan
5               Manhattan, NY                    nan     nan
6               Ultilagro, CT                    nan     nan
7                       Japan                    nan     nan
8                         nan                    nan     nan
9  4543.34GBP (British Pound)                    nan     nan

, если вы хотите использовать оператор where:

import numpy as np



df["3"] = np.where(
    df[df["2"].str.contains("phone", case=False)], df["0"].str.extract(r"([V]\w+)"), np.nan
)
            print(df[['0','2','3']])
                                   0                      2       3
        1              Reference Curr  Invoice Date Due Date     NaN
        2            V50011 Tech Comp       Phone:0177222222  V50011
        3                 Regis Place       Fax:017757575789     NaN
        4                  Catenberry                    nan     NaN
        5               Manhattan, NY                    nan     NaN
        6               Ultilagro, CT                    nan     NaN
        7                       Japan                    nan     NaN
        8                         nan                    nan     NaN
        9  4543.34GBP (British Pound)                    nan     NaN
0 голосов
/ 16 января 2020

Вы можете сделать это с помощью функции pandas apply:

import re
import numpy as np
import pandas as pd
df['Company'] = df.apply(lambda x: x[0].split()[0] if re.match(r'^v[A-Za-z0-9]+', x[0].lower()) and 'phone' in x[1].lower() else np.nan, axis=1)

Редактировать:

Для корректировки комментариев под ответом @ AM C

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...