Частичное совпадение строк в большом наборе данных - PullRequest
0 голосов
/ 11 сентября 2018

Так что я работал над этим некоторое время и просто не нашел, где и просто не уверен, что делать. Совершенно новый для панд и питона.

На самом деле набор данных - это 15 000 наименований продуктов.Все в разных форматах, некоторые имеют несколько тире до 6, некоторые дефисы, разной длины. Строки - это названия продуктов с вариантами.

Код, который я использую, возвращает только первую букву в отличие от частичнойкогда я использую его для большого набора данных.

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

Я предполагаю, что это происходит потому, что:

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

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

Исходный набор тестовых данных

`1.star t-shirt-large-red
 2.star t-shirt-large-blue
 3.star t-shirt-small-red
 4.beautiful rainbow skirt small
 5.long maxwell logan jeans- light blue -32L-28W
 6.long maxwell logan jeans- Dark blue -32L-28W`

Требуемый набор / вывод данных:

 `COL1                             COL2         COL3    COL4
  1[star t-shirt]                  [large]      [red]    NONE
  2[star t-shirt]                  [large]      [blue]   NONE
  3[star t-shirt]                  [small]      [red]    NONE
  4[beautiful rainbow skirt small] [small]       NONE   NONE
  5[long maxwell logan jeans]      [light blue] [32L]  [28W]
  6[long maxwell logan jeans]      [Dark blue]  [32L]  [28W]`

Вот код Iмне помогли в предыдущем вопросе, который я задал:

`df['onkey'] = 1
 df1 = pd.merge(df[['name','onkey']],df[['name','onkey']], on='onkey')
 df1['list'] = df1.apply(lambda x:[x.name_x,x.name_y],axis=1)
 from os.path import commonprefix
 df1['COL1'] = df1['list'].apply(lambda x:commonprefix(x))
 df1['COL1_num'] = df1['COL1'].apply(lambda x:len(x))
 df1 = df1[(df1['COL1_num']!=0)]
 df1 = df1.loc[df1.groupby('name_x')['COL1_num'].idxmin()]
 df = df.rename(columns ={'name':'name_x'})
 df = pd.merge(df,df1[['name_x','COL1']],on='name_x',how ='left')`


`df['len'] = df['COL1'].apply(lambda x: len(x))
 df['other'] = df.apply(lambda x: x.name_x[x.len:],axis=1)
 df['COL1'] = df['COL1'].apply(lambda x: x.strip())
 df['COL1'] = df['COL1'].apply(lambda x: x[:-1] if x[-1]=='-' else x)
 df['other'] = df['other'].apply(lambda x:x.split('-'))
 df = df[['COL1','other']]
 df = pd.concat([df['COL1'],df['other'].apply(pd.Series)],axis=1)`

`                                      COL1            0     1    2
0                   star t-shirt        large   red  NaN
1                   star t-shirt        large  blue  NaN
2                   star t-shirt        small   red  NaN
3  beautiful rainbow skirt small                NaN  NaN
4       long maxwell logan jeans  light blue    32L  28W
5       long maxwell logan jeans   Dark blue    32L  28W`

*************** обновление *****************

  1. Это ваш входной список товаров, у некоторых есть варианты, а у некоторых нет.
  2. При поиске дублирующихся строк, чтобы определить, какие товары имеют варианты, а какие нет.варианты, ничего не появляется, потому что все они рассматриваются как уникальные значения из-за вариантов, добавляемых в конце строки.
  3. Итак, я хотел бы сгруппировать частичные или похожие строкивместе (самое длинное совпадение) извлеките самую длинную совпадающую строку в группе, а затем поместите различия в другие столбцы.

  4. Если продукт / строка уникальны, просто напечатайте в столбце с извлеченной самой длинной строкой.

    star t-shirt-large-red star t-shirt-large-blue star t-shirt-small-red beautiful rainbow skirt small long maxwell logan jeans- light blue -32L-28W long maxwell logan jeans- Dark blue -32L-28W Organic and natural candy - 3 Pack - Mint Organic and natural candy - 3 Pack - Vanilla Organic and natural candy - 3 Pack - Strawberry Organic and natural candy - 3 Pack - Chocolate Organic and natural candy - 3 Pack - Banana Organic and natural candy - 3 Pack - Cola Organic and natural candy - 12 Pack Assorted Morgan T-shirt Company - Small/Medium-Blue Morgan T-shirt Company - Medium/Large-Blue Morgan T-shirt Company - Medium/Large-red Morgan T-shirt Company - Small/Medium-Red Morgan T-shirt Company - Small/Medium-Green Morgan T-shirt Company - Medium/Large-Green Nelly dress leopard small

    col1 col2 col3 col4 star t-shirt large red<br> star t-shirt large blue<br> star t-shirt small red<br> beautiful rainbow skirt small<br> Long maxwell logan jeans light blue 32L 28W Long maxwell logan jeans Dark blue 32L 28W Organic and natural candy 3 Pack Mint Organic and natural candy 3 Pack Vanilla<br> Organic and natural candy 3 Pack Strawberry<br> Organic and natural candy 3 Pack Chocolate<br> Organic and natural candy 3 Pack Banana<br> Organic and natural candy 3 Pack Cola Organic and natural candy 12 Pack Assorted Morgan T-shirt Company Small/Medium Blue Morgan T-shirt Company Medium/Large Blue Morgan T-shirt Company Medium/Large Red<br> Morgan T-shirt Company Small/Medium Red<br> Morgan T-shirt Company Small/Medium Green<br> Morgan T-shirt Company Medium/Large Green<br> Nelly dress Leopard Small<br> Bijoux<br> Princess PJ-set<br> Lemon tank top Yellow Medium

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Решение, которое довольно просто понять, отладить и гибко расширить, состоит в следующем:

Учтите, что ваши первоначальные названия продуктов содержатся в списке под названием strings.

Тогда решением будет следующая строка :

mydf = pd.concat([pd.DataFrame([make_row(row, 4)], columns=['COL1', 'COL2', 'COL3', 'COL4']) for row in strings],  ignore_index=True)

где мы определили функцию синтаксического анализа make_row:

def make_row(string, num_cols):
    cols = [item.strip() for item in string[2:].split('-')] # ignore numbering, split on hyphen and strip whitespace
    if len(cols) < num_cols:
        cols += [np.nan]*(num_cols - len(cols)) # fill with NaN missing values
    return cols

Первая строка, определяющая cols, также может быть просто cols = string.split('-'), и в этом случае вы можете выполнить форматирование впоследствии с помощью:

mydf.applymap(lambda x: x if pd.isnull(x) else str.strip(x))

Теперь, в вашем случае, я вижу, что в некоторых названиях ваших продуктов есть дефис, и в этом случае вы можете захотеть «санировать» их заранее (или внутри make_row, как вы хотите), с чем-то вроде :

strings = [item.replace('t-shirt', 'tshirt') for item in strings]

Пример ввода :

strings = ['1.one-two-three', '2. one-two', '3.one-two-three-four', '4.one - two -three  -four ']

выход :

  COL1 COL2   COL3  COL4
0  one  two  three   NaN
1  one  two    NaN   NaN
2  one  two  three  four
3  one  two  three  four

Вывод данных вопроса (после исправления опечатки для пункта 4):

                       COL1        COL2  COL3 COL4
0               star tshirt       large   red  NaN
1               star tshirt       large  blue  NaN
2               star tshirt       small   red  NaN
3   beautiful rainbow skirt       small   NaN  NaN
4  long maxwell logan jeans  light blue   32L  28W
5  long maxwell logan jeans   Dark blue   32L  28W

Edit:

Если вы дополнительно хотите «сгруппировать» элементы вместе, тогда вы можете:

a) Используйте sort_values ( pandas doc ) в столбце COL1 после получения кадра данных, как описано выше, чтобы просто отображать строки, соответствующие одному и тому же продукту, один за другим, или

b) используйте group_by для фактического получения сгруппированного фрейма данных, подобного этому:

grouped_df = mydf.groupby("COL1")

Это позволит вам получить каждую группу следующим образом:

grouped_df.get_group("star tshirt")

Производит следующий вывод:

          COL1   COL2  COL3 COL4
0  star tshirt  large   red  NaN
1  star tshirt  large  blue  NaN
2  star tshirt  small   red  NaN
0 голосов
/ 11 сентября 2018

Построение DataFrame df следующим образом:

df = pd.DataFrame()
df = df.append(['1.star t-shirt-large-red'])
df = df.append(['2.star t-shirt-large-blue'])
df = df.append(['4.beautiful rainbow skirt small'])
df = df.append(['5.long maxwell logan jeans- light blue -32L-28W'])
df = df.append(['6.long maxwell logan jeans- Dark blue -32L-28W'])

df.columns = ['Product']

Следующий код

(a) удаляет любой пробел,

(b) разбивает на период ('. ') и берет следующее,

(c) заменяет' футболку 'на' футболку 'из-за дальнейших операций (замените это, если хотите после операции)

(d) снова разделяется на «-» и расширяется, давая ваш фрейм данных.

df['Product'].str.strip().str.split('.').str.get(1).str.replace('t-shirt', 'tshirt').str.split('-', expand = True)

Вывод:

                               0             1     2     3
0                    star tshirt         large   red  None
0                    star tshirt         large  blue  None
0  beautiful rainbow skirt small          None  None  None
0       long maxwell logan jeans   light blue    32L   28W
0       long maxwell logan jeans    Dark blue    32L   28W

Учитывая несоответствие в номенклатуре для вашего продукта, будут крайние случаи, которыепропущены (например: beautiful rainbow skirt small).Возможно, вам придется выловить их снова.

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