Как добавить список элементов в один элемент данных? - PullRequest
1 голос
/ 24 июня 2019

У меня есть два фрейма данных, для актеров, у которых есть функция, которая представляет собой список номеров идентификаторов фильмов для фильмов, над которыми они работали. У меня также есть список фильмов, у которых есть идентификационный номер, который будет отображаться в списке актера, если он был в этом фильме.

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

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

Вот датафрейм актеров:

print(actors[['primaryName', 'knownForTitles']].head())
         primaryName                           knownForTitles
0     Rowan Atkinson  tt0109831,tt0118689,tt0110357,tt0274166
1        Bill Paxton  tt0112384,tt0117998,tt0264616,tt0090605
2   Juliette Binoche  tt1219827,tt0108394,tt0116209,tt0241303
3   Linda Fiorentino  tt0110308,tt0119654,tt0088680,tt0120655
4  Richard Linklater  tt0243017,tt1065073,tt2209418,tt0405296

И кадр данных фильмов:

print(movies[['tconst', 'primaryTitle']].head())
      tconst                 primaryTitle
0  tt0001604            The Fatal Wedding
1  tt0002467          Romani, the Brigand
2  tt0003037   Fantomas: The Man in Black
3  tt0003593  Across America by Motor Car
4  tt0003830       Detective Craig's Coup

Как видите, идентификатор movies['tconst'] отображается в списке в кадре данных актеров.

Моя очень медленная итерация по фрейму данных фильма выглядит следующим образом:

def add_cast(movie_df, actor_df):

    results = movie_df.copy()
    length = len(results)

    #create an empty feature 
    results['cast'] = ""

    #iterate through the movie identifiers
    for index, value in results['tconst'].iteritems():
        #create a new dataframe containing all the cast associated with the movie id
        cast = actor_df[actor_df['knownForTitles'].str.contains(value)]


        #check to see if the 'primaryName' list is empty
        if len(list(cast['primaryName'].values)) != 0:
            #set the new movie 'cast' feature equal to a list of the cast names
            results.loc[index]['cast'] = list(cast['primaryName'].values)

        #logging
        if index % 1000 == 0:
            logging.warning(f'Results location: {index} out of {length}')

        #delete cast df to free up memory
        del cast

    return results

Это дает некоторые результаты, но недостаточно быстро, чтобы быть полезным. Одно из наблюдений состоит в том, что, создавая новый фрейм данных всех актеров, у которых есть идентификатор фильма в их knownForTitles, можно заключить, что этот список можно поместить в одну особенность фрейма данных фильмов.

В то время как моя попытка перебрать нижеприведенный кадр данных об актерах, я не могу добавить элементы в кадр данных фильмов:

def actors_loop(movie_df, actor_df):

    results = movie_df.copy()
    length = len(actor_df)


    #create an empty feature 
    results['cast'] = ""

    #iterate through all actors
    for index, value in actor_df['knownForTitles'].iteritems():


        #skip empties
        if str(value) == r"\N":
            logging.warning(f'skipping: {index} with a value of {value}')
            continue

        #generate a list of movies that this actor has been in
        cinemetography = [x.strip() for x in value.split(',')]

        #iterate through every movie the actor has been in
        for movie in cinemetography:

            #pull out the movie info if it exists
            movie_info = results[results['tconst'] == movie]

            #continue if empty
            if len(movie_info) == 0:
                continue

            #set the cast variable equal to the actor name
            results[results['tconst'] == movie]['cast'] = (actor_df['primaryName'].loc[index])

            #delete the df to save space ?maybe
            del movie_info

        #logging
        if index % 1000 == 0:
            logging.warning(f'Results location: {index} out of {length}')

    return results

Так что, если я запускаю приведенный выше код, я получаю очень быстрый результат, но поле «cast» остается пустым.

1 Ответ

0 голосов
/ 27 июня 2019

Я выяснил проблему, с которой столкнулся с функцией def actors_loop(movie_df, actor_df).Проблема заключается в том, что

results['tconst'] == movie]['cast'] = (actor_df['primaryName'].loc[index])

устанавливает значение, равное копии кадра данных results.Было бы лучше использовать метод df.set_value() или метод df.at[].

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

def actor_tuples(actor_df):
    tuples =[]
    for index, value in actor_df['knownForTitles'].iteritems():

        cinemetography = [x.strip() for x in value.split(',')]
        for movie in cinemetography:
            tuples.append((actor_df['primaryName'].loc[index], movie))
    return tuples

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

[('Fred Astaire', 'tt0043044'),
 ('Lauren Bacall', 'tt0117057')]

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

{'tt0000009': 0,
 'tt0000147': 1,
 'tt0000335': 2,
 'tt0000502': 3,
 'tt0000574': 4,
 'tt0000615': 5,
 'tt0000630': 6,
 'tt0000675': 7,
 'tt0000676': 8,
 'tt0000679': 9}

Затем я использовал приведенную ниже функцию для итерации по кортежам актеров и использовал идентификатор фильма в качестве ключа в словаре фильма, это вернуло правильный фильмindex, который я использовал, чтобы добавить кортеж с именем актера в целевой фрейм данных:

def add_cast(movie_df, Atuples, Mtuples):
    results_df = movie_df.copy()
    results_df['cast'] = ''
    counter = 0
    total = len(Atuples)


    for tup in Atuples:
        #this passes the movie ID into the movie_dict that will return an index
        try:
            movie_index = Mtuples[tup[1]]
            if results_df.at[movie_index, 'cast'] == '':
                results_df.at[movie_index, 'cast'] += tup[0]
            else:
                results_df.at[movie_index, 'cast'] += ',' + tup[0]
        except KeyError:
            pass

        #logging
        counter +=1
        if counter % 1000000 == 0:
            logging.warning(f'Index {counter} out of {total}, {counter/total}% finished')

    return results_df

Он работал за 10 минут (создавая 2 набора кортежей, затем добавляя функцию) для 16,5 миллионов кортежей актеров.Результаты ниже:

0  tt0000009                     Miss Jerry      1894                 Romance   
1  tt0000147  The Corbett-Fitzsimmons Fight      1897  Documentary,News,Sport   
2  tt0000335          Soldiers of the Cross      1900         Biography,Drama   
3  tt0000502                       Bohemios      1905                      \N   
4  tt0000574    The Story of the Kelly Gang      1906   Biography,Crime,Drama   

                                                cast  
0  Blanche Bayliss,Alexander Black,William Courte...  
1  Bob Fitzsimmons,Enoch J. Rector,John L. Sulliv...  
2  Herbert Booth,Joseph Perry,Orrie Perry,Reg Per...  
3  Antonio del Pozo,El Mochuelo,Guillermo Perrín,...  
4  Bella Cola,Sam Crewes,W.A. Gibson,Millard John...  

Спасибо, переполнение стека!

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