Попытка создать трехмерную матрицу в Python, выбрав данные c. - PullRequest
1 голос
/ 27 января 2020

Привет, поэтому я пытаюсь сделать 3D матрицу здесь .. Это данные MovieLens (https://grouplens.org/datasets/movielens/100k/), откуда я беру пару u1.base и u1.test в качестве тренировки и тестовые наборы (соответственно). Ниже приведено изображение формата данных переменной training_set, которую вы обнаружите в коде.

enter image description here

3D-матрица Я попытка создания имеет формат (User, Movie, Timestamp), и данные в каждой из этих ячеек представляют собой оценки, заданные, например, пользователем 1 для mov ie 1 в момент времени 1.

Если это поможет, ниже приведен код, в котором 2D-матрица создается с пользователями в строках и всеми фильмами в виде столбцов.

import numpy as np
import pandas as pd

training_set = pd.read_csv('ml-100k/u1.base', delimiter = '\t')
training_set = np.array(training_set, dtype='int')
test_set = pd.read_csv('ml-100k/u1.test', delimiter = '\t')
test_set = np.array(test_set, dtype = 'int64')

nb_users = int(max(max(training_set[:, 0]), max(test_set[:, 0])))
nb_movies = int(max(max(training_set[:, 1]), max(test_set[:, 1]))) 

def convert(data):
    new_data = [] #final list that we will return
    for id_users in range(1, nb_users+1):
        id_movies = data[:, 1][data[:, 0] == id_users] #contains the IDs of the movies rated by the id_user
        id_ratings = data[:, 2][data[:, 0] == id_users] #all movie ratings given by specific user
        ratings = np.zeros(nb_movies)
        ratings[id_movies-1] = id_ratings #these two lines are just so that the movies that are not rated by user have null (0) values
        new_data.append(list(ratings))
    return (new_data)
training_set = convert(training_set)
test_set = convert(test_set)

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

import numpy as np
import pandas as pd
training_set = pd.read_csv('ml-100k/u1.base', delimiter = '\t')
training_set = np.array(training_set, dtype='int')
test_set = pd.read_csv('ml-100k/u1.test', delimiter = '\t')
test_set = np.array(test_set, dtype = 'int64')

nb_users = int(max(max(training_set[:, 0]), max(test_set[:, 0])))
nb_movies = int(max(max(training_set[:, 1]), max(test_set[:, 1])))

#The changes I made start here --

nb_timestamps = int(max(len(training_set[:, 3]), len(test_set[:, 3])))

ts_min = int(min(min(training_set[:, 3]), min(test_set[:, 3])))
ts_max = int(max(max(training_set[:, 3]), max(test_set[:, 3])))


def convert(data):
    new_data = [] #final list that we will return
    for timestamp in range(ts_min, ts_max+1):
        for id_users in range(1, nb_users+1):
            id_movies = data[:, 1][data[:, 0] == id_users][data[:, 3] == timestamp]
            #contains the IDs of the movies rated by the id_user
            id_ratings = data[:, 2][data[:, 0] == id_users][data[:, 3] == timestamp]
            ratings = np.zeros(nb_movies)
            ratings[id_movies-1] = id_ratings
        new_data.append(list(ratings))
    return (new_data)
training_set = convert(training_set)
test_set = convert(test_set)

1 Ответ

1 голос
/ 27 января 2020

Примечание: Пожалуйста, не принимайте это как ответ (пока).

В вашем коде есть несколько вещей, которые можно улучшить:

  • Когда вы читаете CSV, вы берете первую строку в качестве заголовка, что означает, что вы не учитываете все данные
  • Если в этом случае (как и должно быть), есть только один пользователь Вы можете оценить mov ie только один раз, когда вы можете использовать pd.pivot_table для получения 2D-матрицы.
import pandas as pd
import numpy as np
training_set = pd.read_csv('ml-100k/u1.base',
                           delimiter='\t',
                           header=None, # First row is not header
                           names=["user", "movie",
                                  "rating", "timestamp"]) # rename headers

# with pd.pivot_table you get a df where user are in rows 
# and movies in columns. The value is the rating for movie (i,j)
ratings = pd.pivot_table(training_set,
                         index=["user"],
                         columns=["movie"],
                         values="rating")

Если вы хотите 0s вместо NaN, вы можете используйте ratings.fillna(0). Но я бы так не поступил. Вы должны быть осторожны, потому что это испортит возможную статистику, которую вы хотите извлечь.

Если вам нужна 2D-матрица, вы можете просто использовать ratings.values.

UPDATE

Чтобы получить 3D-матрицу, мы можем сделать то же самое с помощью временных меток

timestamps = pd.pivot_table(training_set,
                         index=["user"],
                         columns=["movie"],
                         values="timestamp")

# get matrix
mat_ratings = ratings.values
mat_timestamps = timestamps.values

# stack matrix
mat3d = np.dstack((mat_ratings, mat_timestamps))

Теперь вы можете проверить, что из 2-х матриц с формой (943, 1650) мы получаем одну из форм (943, 1650, 2). Обратите внимание, чтобы получить форму матрицы mat, просто запустите mat.shape.

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