Python для и цикл if для категоризации

avatar
Sebastián Carmona Ángel
8 августа 2021 в 15:48
108
3
0

У меня есть 2 столбца в кадре данных (обе строки) и отдельный список.

      name   id
0     wine     2
1     beer     4
2     cheese   6
3     yogurt   8
4     choc     10
5     whisky   12

list = ["beers","wines","whiskies","chocolates and candy","cheeses","yogurts"]

Я хочу сравнить список и столбец "имя" и создать новый столбец в качестве "категории", который будет одним из списка

ожидаемый результат:

      name   id   category
0     wine     2   wines
1     beer     4   beers
2     cheese   6   cheeses
3     yogurt   8   yogurts
4     choc     10  chocolates and candy
5     whisky   12  whiskies

Я начал с чего-то вроде этого

from difflib import SequenceMatcher
def similar(a, b):
    return SequenceMatcher(None, a, b).ratio()

for i in df["name"]:
    for x in subcategory:
        z = similar(i,x)
        if z >= 0.60: 

но не знал что делать, заблокировали

Источник

Ответы (3)

avatar
fsimonjetz
8 августа 2021 в 16:45
1

Если вы используете pandas, вы также можете использовать его возможности (то есть векторизацию).

# note: do not use builtin names like 'list' as variable names
categories = ["beers", "wines", "whiskies", "chocolates and candy", "cheeses", "yogurts"]

def get_category(cat, f):
    return max(categories, key=lambda x: f(cat, x))

df['category'] = df['name'].apply(get_category, f=similar)

Ваша функция similar возвращает "сыр" вместо "шоколад", но в этом подходе хорошо (кроме того, что он намного быстрее и лаконичнее, чем iterrows), вы можете указать любое сходство -функция, которая вам нравится, и попробуйте разные показатели, например. нечеткое сопоставление строк здесь может быть вариантом: partial_ratio дает правильный результат для вашего примера:

>>> from fuzzywuzzy import fuzz
>>> df['category'] = df['name'].apply(get_category, f=fuzz.partial_ratio)
>>> df
     name  id              category
0    wine   2                 wines
1    beer   4                 beers
2  cheese   6               cheeses
3  yogurt   8               yogurts
4    choc  10  chocolates and candy
5  whisky  12              whiskies
Sebastián Carmona Ángel
9 августа 2021 в 18:09
0

Это мне очень помогло, большое спасибо, но у меня есть вопрос, вы не знаете, можно ли это сделать с испанскими словами?

fsimonjetz
9 августа 2021 в 18:19
0

Я не могу обещать, что это будет на 100% правильно во всех случаях, но это определенно работает для испанского языка.

avatar
Piotr Żak
8 августа 2021 в 16:24
0

импорт панд как pd импортировать numpy как np

df = pd.DataFrame(np.array([['wine', 2], ['beer', 4,], ['cheese', 6, ]]),
                   columns=['a', 'b', ])

df['Similarity'] = 0
df['Category'] = 0

from difflib import SequenceMatcher
def similar(a, b):
    return SequenceMatcher(None, a, b).ratio()

    for index, row in df.iterrows(): 
        for x in list:
            z = similar(row['a'],x)
            if z >= 0.60: 
                df.loc[index, "Similarity"] = z
                df.loc[index, "Category"] = x
    

результат:

enter image description here

avatar
Anton van der Wel
8 августа 2021 в 16:05
0

Если я правильно понял ваш вопрос, вы хотите создать новый столбец на основе некоторой логики.

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

import pandas as pd

sampledata = {'name': ['wine', 'beer', 'cheese', 'yoghurt'], 'id': [2, 4, 6, 8]}  

dataframe = pd.DataFrame(data=sampledata)

newcolum = []

for index, row in dataframe.iterrows():
    #Do your logic here:
    if row["name"] == "wine":
        newcolum.append("wines")
    else:
        newcolum.append("not wines") 

dataframe["category"] = newcolum

print(dataframe.head())

вывод:

      name  id   category
0     wine   2      wines
1     beer   4  not wines
2   cheese   6  not wines
3  yoghurt   8  not wines