Pandas: если строка в столбце A содержит "x", напишите "y" для строки в столбце B

Для pandas я ищу способ записи условных значений в каждую строку в столбце B на основе подстрок для соответствующих строк в столбце A.

Поэтому, если ячейка в A содержит "BULL", напишите "Long" в B Или, если ячейка в A содержит "BEAR", напишите "Short" на B

Желаемый результат:

A                  B
"BULL APPLE X5"    "Long"
"BEAR APPLE X5"    "Short"
"BULL APPLE X5"    "Long"

B первоначально пусто: df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']],columns=['A','B'])

Ответ 1

Ваш код будет ошибочным при неправильном создании Dataframe, просто создайте один столбец A затем добавьте B на основе A:

import pandas as pd
df = pd.DataFrame(["BULL","BEAR","BULL"], columns=['A'])
df["B"] = ["Long" if ele  == "BULL" else "Short" for ele in df["A"]]

print(df)

    A      B
0  BULL   Long
1  BEAR  Short
2  BULL   Long

Или вы логики с данными перед созданием dataframe:

import pandas as pd
data = ["BULL","BEAR","BULL"]
data2 = ["Long" if ele  == "BULL" else "Short" for ele in data]
df = pd.DataFrame(list(zip(data, data2)), columns=['A','B'])

print(df)
      A      B
 0  BULL   Long
 1  BEAR  Short
 2  BULL   Long

Для вашего редактирования:

df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']], columns=['A','B'])

df["B"] = df["A"].map(lambda x: "Long" if "BULL" in x else "Short" if "BEAR" in x else "")

print(df)

            A      B
0  BULL APPLE X5   Long
1  BEAR APPLE X5  Short
2  BULL APPLE X5   Long

Или просто добавьте столбец после:

df = pd.DataFrame(['BULL APPLE X5','BEAR APPLE X5','BLL APPLE X5'], columns=['A'])

df["B"] = df["A"].map(lambda x: "Long" if "BULL" in x else "Short" if "BEAR" in x else "")

print(df)

Или использование содержит:

df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']], columns=['A','B'])


df["B"][df['A'].str.contains("BULL")] = "Long"
df["B"][df['A'].str.contains("BEAR")] = "Short"

print(df)
0  BULL APPLE X5   Long
1  BEAR APPLE X5  Short
2  BULL APPLE X5   Long

Ответ 2

Вы можете использовать str.extract для поиска шаблона регулярного выражения BULL|BEAR, а затем использовать Series.map для замены этих строк Long или Short:

In [50]: df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']],columns=['A','B'])

In [51]: df['B'] = df['A'].str.extract(r'(BULL|BEAR)').map({'BULL':'Long', 'BEAR':'Short'})

In [55]: df
Out[55]: 
               A      B
0  BULL APPLE X5   Long
1  BEAR APPLE X5  Short
2  BULL APPLE X5   Long

Однако формирование промежуточной серии с str.extract довольно медленно по сравнению с df['A'].map(lambda x:...) str.extract df['A'].map(lambda x:...). Используя IPython %timeit для времени тестов,

In [5]: df = pd.concat([df]*10000)

In [6]: %timeit df['A'].str.extract(r'(BULL|BEAR)').map({'BULL':'Long', 'BEAR':'Short'})
10 loops, best of 3: 39.7 ms per loop

In [7]: %timeit df["A"].map(lambda x: "Long" if "BULL" in x else "Short" if "BEAR" in x else "")
100 loops, best of 3: 4.98 ms per loop

Большая часть времени проводится в str.extract:

In [8]: %timeit df['A'].str.extract(r'(BULL|BEAR)')
10 loops, best of 3: 37.1 ms per loop

в то время как вызов Series.map относительно быстр:

In [9]: x = df['A'].str.extract(r'(BULL|BEAR)')

In [10]: %timeit x.map({'BULL':'Long', 'BEAR':'Short'})
1000 loops, best of 3: 1.82 ms per loop

Ответ 3

Кроме того, для df['B'] вы можете попробовать метод ниже:

def applyFunc(s):
    if s == 'BULL':
        return 'Long'
    elif s == 'BEAR':
        return 'Short'
    return ''

df['B'] = df['A'].apply(applyFunc)
df
>>
       A      B
0  BULL   Long
1  BEAR  Short
2  BULL   Long

Что делает функция apply, то для каждого значения строки df['A'] она вызывает функцию applyFunc с параметром в качестве значения этой строки, а возвращаемое значение помещается в ту же строку для df['B'], то, что действительно происходит за сценой, немного отличается, но значение прямо не помещается в df['B'] а создается новая Series и в конце новая серия назначается df['B'].