Разделите столбец с произвольным количеством элементов на новый фрейм данных и назначьте дополнительные значения

#python #dataframe

Вопрос:

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

Примеры данных:

movieid директора бросать
1 персона 1, персона 2, персона 3 персона 4, персона 6, персона 7
2 персона 1, персона 3 персона 4, персона 5, персона 9, персона 11

Мне нужна нижняя таблица, но итерация кажется медленной (9 тысяч строк заняли минуту).

 import pandas as pd
import numpy as np

data = pd.read_csv(datafile, sep=str, delimiter=',', encoding='utf-8')
data2 = data[['show_id','director','cast']].copy()
data2[['cast', 'director']] = data2[['cast', 'director']].fillna('none')

df = pd.DataFrame(columns= ['show_id','role','name'])

for row in data2.itertuples():
    casts = row.cast.split(',')
    directors = row.director.split(',')
    for member in casts:
        new_row = {'id': row.show_id, 'role':'cast', 'name': member}
        df = df.append(new_row, ignore_index=True)
    for member in directors:
        new_row = {'id': row.show_id, 'role':'director', 'name': member}
        df = df.append(new_row, ignore_index=True)
 

новые ЛИЦА df

movieid Роль Имя
1 директор персона1
1 директор персона 2
1 бросать персона4
1 бросать персона7

Комментарии:

1. Я думаю, вы не хотите, чтобы третий столбец новой таблицы данных был «отлит», верно? «персона 1» и «персона 2» не являются участниками приведения, поэтому иметь имя столбца «приведение» не имеет смысла. Разве» приведение» не должно быть «ролью», которая отображается как значение во втором столбце? Разве имя столбца не должно быть чем-то вроде «имя» или «человек»? Итак, вам нужна запись в этой новой таблице для каждого человека в каждом фильме, верно? Так почему бы не повторить, как вы говорите? Что в этом плохого? Это будет хорошим упражнением, если вы начинающий программист. У вас есть вопрос? Не похоже, что ты об этом спрашивал.

2. Приношу свои извинения, когда я что-то исправлял, колонки сдвигались при копировании и вставке. Фиксирующий.

3. является ли актерский состав также ролью?

4. Да, актерский состав-это актер/актриса. Я хочу создать таблицу персон, в которой будет указана роль человека (продюсера, режиссера и т. Д.) Для фильма.

Ответ №1:

Один из способов избежать зацикливания-это использовать DataFrame.melt и Series.str.split .

Использование выборочных данных:

 import pandas as pd
from io import StringIO

data = '''
movieid;director;cast
1;person 1, person 2, person 3;person 4, person 6, person 7
2;person 1, person 3;person 4, person 5, person 9, person 11
'''
df = pd.read_csv(StringIO(data), sep=';')

# movieid                      director                                     cast
#       1  person 1, person 2, person 3             person 4, person 6, person 7
#       2            person 1, person 3  person 4, person 5, person 9, person 11
 
  1. melt в movie / role / names_csv :
 df = df.melt(id_vars='movieid', var_name='role', value_name='names_csv')

# movieid      role                                names_csv
#       1  director             person 1, person 2, person 3
#       2  director                       person 1, person 3
#       1      cast             person 4, person 6, person 7
#       2      cast  person 4, person 5, person 9, person 11
 
  1. split names_csv строки в развернутые столбцы:
 df = (df.names_csv.str.split(r',s*', expand=True)
        .join(df[['movieid', 'role']]))

#        0         1         2          3  movieid      role
# person 1  person 2  person 3       None        1  director
# person 1  person 3      None       None        2  director
# person 4  person 6  person 7       None        1      cast
# person 4  person 5  person 9  person 11        2      cast
 
  1. melt снова, на этот раз в movie / role / name (при желании с некоторым удалением и сортировкой):
 df = (df.melt(id_vars=['movieid', 'role'], value_name='name')
   .drop('variable', axis=1).dropna()
   .sort_values(['movieid', 'role'], ascending=[True, False], ignore_index=True))

# movieid      role       name
#       1  director   person 1
#       1  director   person 2
#       1  director   person 3
#       1      cast   person 4
#       1      cast   person 6
#       1      cast   person 7
#       2  director   person 1
#       2  director   person 3
#       2      cast   person 4
#       2      cast   person 5
#       2      cast   person 9
#       2      cast  person 11