Вложенные списки в ячейках панд данных, как извлечь? - PullRequest
0 голосов
/ 22 октября 2018

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

изображение кадра данных

df_final['Product Name'] = ('dr. jart+ mask heroes face savers', 
                       'moon juice beauty shroom exfoliating acid 
                        potion',
                       'laneige kiss and make up set')

df_final['Subreddit'] = (None, ['scacjdiscussion'], ['AsianBeauty', 
                   'AsianBeautyAdvice','SkincareAddiction', 
                   'abdiscussion'])

df_final['Times Mentioned'] = (None, [1], [4,1,1,1])

Я хочу, чтобы ячейки в столбце «Subreddit» стали новыми столбцами, а ячейки вКолонка «Times Menseed» для заполнения новых ячеек.Столбец «Имя продукта» будет новым индексом.

Я пытался использовать pivot_table -

from pandas import pivot_table

table = pivot_table(df_final, values='Times Mentioned', index=['Product 
        Name'], columns=['Subreddit'], aggfunc='size')

Это успешно превратило все вложенные списки столбца «Subreddit» в новые столбцы, но«Упомянутое время» просто повторяет первое число для каждого столбца (пример ниже)

неправильные заполнители ячеек

Это должно быть 4, 1, 1, 1, как воригинальное изображение.Кто-нибудь знает, как это исправить?

Заранее спасибо!

1 Ответ

0 голосов
/ 22 октября 2018

В DF есть несколько ячеек, которые содержат список

['AsianBeauty', 'AsianBeautyAdvice','SkincareAddiction', 'abdiscussion']

, и это отдельная ячейка, которую необходимо разбить на отдельные строки в одном и том же столбце (Product Name).Однако это должно быть сделано при сохранении ассоциации между столбцом Product Name и каждым из двух других столбцов (которые содержат строки, которые должны быть разбиты).Я использовал этот пост , чтобы сделать именно это, сохраняя при этом связь нетронутой.Вот подход, который я использовал, с комментариями в коде и объяснением верхнего уровня, показанными отдельно

Raw DF от OP

import pandas as pd


df_final = pd.DataFrame()
df_final['Product Name'] = ('dr. jart+ mask heroes face savers', 
                           'moon juice beauty shroom exfoliating acid potion',
                           'laneige kiss and make up set')

df_final['Subreddit'] = (None, ['scacjdiscussion'], ['AsianBeauty', 
                       'AsianBeautyAdvice','SkincareAddiction', 
                       'abdiscussion'])

df_final['Times Mentioned'] = (None, [1], [4,1,1,1])
print(df_final)

Необработанные данные (df_final)

                                       Product Name                                                          Subreddit Times Mentioned
0                 dr. jart+ mask heroes face savers                                                               None            None
1  moon juice beauty shroom exfoliating acid potion                                                  [scacjdiscussion]             [1]
2                      laneige kiss and make up set  [AsianBeauty, AsianBeautyAdvice, SkincareAddiction, abdiscussion]    [4, 1, 1, 1]

Столбец необработанных данных dtypes

print(df_final.dtypes)
Product Name       object
Subreddit          object
Times Mentioned    object
dtype: object

Код для разнесения строк и создания окончательного DF

exploded_dfs = []
for _, row in df_final.iterrows():
    if all(row): # if a row does contain all non-None values
        # Put 1st pair of columns into single DF, exploding single
        # cell into multiple rows as needed
        df1 = pd.concat([pd.Series(row['Product Name'], row['Subreddit'][:])])\
                          .reset_index()
        # Assign column names
        df1.columns = ['Subreddit', 'Product Name']
        # Put 2nd pair of columns into single DF, exploding single
        # cell into multiple rows as needed
        df2 = pd.concat([pd.Series(row['Product Name'], row['Times Mentioned'][:])])\
                           .reset_index()
        # Assign column names
        df2.columns = ['Times Mentioned', 'Product Name']
        # Perform INNER JOIN on DFs with exploded row contents
        # & drop duplicated column
        merged = pd.concat([df1, df2], axis=1)
        merged = merged.loc[:,~merged.columns.duplicated()]
        # Swap 1st and 2nd columns
        cols = list(merged)
        cols.insert(0, cols.pop(cols.index('Product Name')))
        merged = merged.loc[:, cols]
    else: # if a row does not contain all non-None values
        # Create single row DF with no changes
        merged = pd.DataFrame(columns=['Product Name', 'Subreddit',
                                      'Times Mentioned'])
        # Append row to DF
        merged.loc[0] = row
    exploded_dfs.append(merged)

# Vertically concatenate DFs in list
print(pd.concat(exploded_dfs, axis=0).reset_index(drop=True))

Вот вывод

                                       Product Name          Subreddit Times Mentioned
0                 dr. jart+ mask heroes face savers               None            None
1  moon juice beauty shroom exfoliating acid potion    scacjdiscussion               1
2                      laneige kiss and make up set        AsianBeauty               4
3                      laneige kiss and make up set  AsianBeautyAdvice               1
4                      laneige kiss and make up set  SkincareAddiction               1
5                      laneige kiss and make up set       abdiscussion               1

Краткое объяснение шагов

  • итерации по всем строкам
    • обратите внимание, что если строка содержит какие-либо значения None, она будет принята как есть, поэтомупредполагается, что эта строка не нуждается в очистке: эта строка будет просто добавлена ​​к одной строке DF
  • для первой строки в необработанном DF, который не содержит всеNone
    • разнесите ячейку из первого столбца со списком (Subreddit) в столбец, если необходимо (объяснено в этот вопрос )
    • горизонтально сцепленная взорванная ячейка (теперьв виде нескольких строк) со строкой из столбца без списка (Product Name);это дает очищенному DF df1
    • повторение последних 2 шагов выше, используя второй столбец со списком (Times Mentioned);это дает очищенному DF df1
    • по горизонтали объединить 2 очищенных DF в новый DF с именем merged
    • , повторите описанную выше процедуру для всех строк в необработанном DF и добавьте очищенный DF в пустой список
    • собрать окончательный DF с вертикальной конкатенацией всех DF в списке

Информация о пакете

pandas==0.23.4

Версия Python

Python 2.7.15rc1
...