Я пытаюсь назначить одну из 8 меток моим данным на основе строк в существующем столбце. Однако, с помощью метода, который я использую, я получаю эту ошибку:

ValueError: Значение истинности Серии неоднозначно. Используйте a.empty, a.bool (), a.item (), a.any () или a.all ().

У меня 144 строки, которые я ищу, и которые я хочу назначить 8 ярлыкам.

Вот упрощенный пример того, что я имею в виду. Если A - это существующий столбец в моем фрейме данных, я хочу создать B со строками, назначенными в зависимости от значения A.

Кадр данных:

   A     B
0  1   low
1  1   low
2  2   mid
3  3   mid
4  5  high
5  4   mid
6  2   mid
7  5  high

Код, который я сейчас использую, выглядит примерно так:

for index, row in df.iterrows():
    if df['A'] == 1:
        df['Label'] = 'low'
    elif any([df['A'] == 2, df['A'] == 3, df['A'] == 4]):
        df['Label'] = 'mid'
    elif df['A'] == 5:
        df['Label'] = 'high'

Я думаю, что использование any () дает мне ошибку. Насколько я понимаю, это из-за того, как работают панды, но я не совсем понимаю. Есть ли более простой способ сделать это?

Любая помощь или указатели будут оценены :)

3
ShrutiTurner 1 Июл 2019 в 15:10

4 ответа

Лучший ответ

Здесь нет необходимости itterrows, что является плохой практикой и считается медленным.

Метод 1 pd.cut

df['B'] = pd.cut(df['A'], [0,1,4,10], labels=['low', 'mid', 'high'])

   A     B
0  1   low
1  1   low
2  2   mid
3  3   mid
4  5  high
5  4   mid
6  2   mid
7  5  high

Метод 2 np.select

conditions = [
    df['A'] == 1,
    df['A'].isin([2, 3, 4])
]

choices = ['low', 'mid']

df['B'] = np.select(conditions, choices, default='high')

   A     B
0  1   low
1  1   low
2  2   mid
3  3   mid
4  5  high
5  4   mid
6  2   mid
7  5  high
3
Erfan 1 Июл 2019 в 12:32

Почему бы вам просто не создать функцию и не применить ее к столбцу, так легко, так питонно

def mapper(x):
     if x == 1:
        return 'low'
     elif x for i in [2, 3, 4]):
        return 'mid'
     elif x == 5:
        return 'high'
     else:
        return 'wtf'

df['B'] = df['A'].apply(mapper)

Другим способом может быть создание фрейма данных из словаря отображения и создание объединения, это еще более интуитивно понятно

Или другой способ - использовать функцию карты для серии карты. функция

В идеале я бы предпочел идти снизу вверх по возрастанию сложности

1
Itachi 1 Июл 2019 в 12:43

Используйте .loc с условиями в индексе следующим образом:

import pandas as pd
from io import StringIO

df = pd.read_csv(StringIO("""
   A
0  1
1  1
2  2
3  3
4  5
5  4
6  2
7  5
"""), sep=r"\s+")

df.loc[df["A"] == 1, "B"] = "low"
df.loc[df["A"].isin((2, 3, 4)), "B"] = "mid"
df.loc[df["A"] == 5, "B"] = "high"

print(df)

Выход:

   A     B
0  1   low
1  1   low
2  2   mid
3  3   mid
4  5  high
5  4   mid
6  2   mid
7  5  high
0
Adam.Er8 1 Июл 2019 в 12:21

Ответ от @ anky_91 в комментариях решил проблему просто:

l=[df.A.eq(1),df.A.isin([2,3,4]),df.A.eq(5)]
df['B']=np.select(l,['low','mid','high'])

Это намного быстрее и работает хорошо.

Спасибо всем за помощь! :)

0
ShrutiTurner 1 Июл 2019 в 12:24