2015-01-19 7 views
0
user_id char_id rating 
100   33   3 
100   44   2 
100   33   1 
100   44   4 
111   55   5 
111   44   4 
111   55   5 

У меня есть кадр данных в формате так же к этому и пытаюсь выполнить расчеты по рейтингам после того как они были сгруппированы по user_id и char_id. Не работает, но мне нужно сделать что-то вроде data.groupby('user_id', 'char_id'), а затем рассчитать скользящую среднюю за каждые char_id за каждые user_id. Любая помощь? У меня есть несколько тысяч user_id, поэтому я не могу пройти и выбирать по одному для вычислений.Выполнение расчетов на подмножества данных кадра подмножества в Python

Мне нужно как-то перебрать столбец user_id и объединить все одинаковые user_ids вместе и сохранить этот формат, чтобы user_id s были отдельными. Затем мне нужно сделать то же самое, итерации по char_id для каждого подмножества user_id и сохранения этого формата, чтобы я мог, наконец, выполнить вычисления на подмножествах подмножеств рейтингов. Пока все мои попытки не увенчались успехом. Ближайший я пришел было:

def divide_by_user(data): 
    for user in data['user_id']: 
     user_data = data.where(data['user_id'] == user) 
     return user_data 

ответ

2

Там нет необходимости делать это вручную, создавая и подведение подмножества, как это именно то, что DataFrame.groupby() для. Создайте свою группу:

grouped = df.groupby(['user_id', 'char_id']) 

Тогда вы можете применить функцию к каждому подмножеству. Это звучит, как вы хотите, либо rolling_mean или expanding_mean, оба из которых уже доступны в pandas:

df['cum_average'] = grouped['rating'].apply(pd.expanding_mean) 
# New column now contains the average rating for each subset, 
# including all values that have been seen so far. 
df 
Out[43]: 
    user_id char_id rating cum_average 
0  100  33  3   3 
1  100  44  2   2 
2  100  33  1   2 
3  100  44  4   3 
4  111  55  5   5 
5  111  44  4   4 
6  111  55  5   5 

Использование большего случайно сгенерированный набор данных для демонстрации rolling_window():

df = pd.DataFrame({ 
    'user_id': [random.choice([100, 111, 112]) for n in range(n_rows)], 
    'char_id': [random.choice([33, 44, 55]) for n in range(n_rows)], 
    'rating': [random.choice([1, 2, 3, 4, 5]) for n in range(n_rows)] 
}) 
grouped = df.groupby(['user_id', 'char_id']) 
df['cum_average'] = grouped['rating'].apply(pd.rolling_mean, window=7) 
# Output. The rolling average will be NaN until enough values have been 
# observed for that subset, you can change this using the 
# min_periods argument to rolling_window 
df.sort(columns=['user_id', 'char_id']) 
    char_id rating user_id cum_average 
3   33  1  100   NaN 
19  33  2  100   NaN 
22  33  5  100   NaN 
34  33  1  100   NaN 
47  33  1  100   NaN 
48  33  1  100   NaN 
49  33  1  100  1.714286 
51  33  4  100  2.142857 
55  33  2  100  2.142857 
60  33  2  100  1.714286 
66  33  2  100  1.857143 
... 
etc. 
+0

Когда я пытаюсь выполнить код, который вы предоставили с расширением_mean, он запускается, но df ['cum_average'] просто отображает копию df ['rating']. Кроме того, когда я пытаюсь запустить с окном roll_mean из 7 (это именно то, что я искал, спасибо!) Я получаю: AttributeError: объект «Серии» не имеет типа атрибута. – Rachael

+0

@Rachael: Использование 'roll_mean' не должно быть слишком разным, см. Новый пример, который я добавил. Я не уверен, что пошло не так для вас, но вы, возможно, ставили аргумент 'window = 7' в неправильном месте? – Marius

+0

@Rachael: Кроме того, результат 'expand_mean' будет просто копией столбца рейтинга для первого рейтинга в каждом подмножестве, и только после того, как вы получите второе значение в каждом подмножестве, вы увидите разницу. – Marius

0

Попробуйте это: "df" - это dataFrame

среднее = pd.rolling_mean (df.rating, 7)

+0

Это не похоже на подмножества user_id/char_id, описанные в вопросе? – Marius

+0

Да, я вижу, что вы правы, но у меня есть такая же проблема с NaN, даже если вектор длиннее размера окна –

+0

'NaN' появится, если аргумент 'min_periods' больше 1. Таким образом, это не обязательно проблема, это ожидаемое поведение функции, и вы можете ее изменить, если вам это не нравится. Вы можете установить «min_periods» в 1, и он просто даст вам скользящее среднее для всех значений, иначе он ждет, пока он не увидит значения «min_periods», прежде чем он начнет вычислять среднее значение. – Marius

Смежные вопросы