#python #pandas #lambda #iteration #list-comprehension
#python #pandas #лямбда #итерация #понимание списка
Вопрос:
Я впервые использую Stack Overflow. Я совсем новичок в кодировании и Pandas, поэтому, пожалуйста, потерпите меня. Я практикую манипулирование данными, используя Python / Pandas вместо Excel, и я столкнулся со следующей проблемой…
Я пытаюсь стандартизировать значения для определенных столбцов по годам. Мой набор данных довольно мал, поэтому выбранный мной подход (показан ниже) работает хорошо, однако я совершенно уверен, что это не лучший способ выполнить эту задачу. Есть ли лучший способ сделать это с помощью понимания списка или применения функции к фрейму данных? (P.S. любые другие ресурсы, которые вы могли бы порекомендовать для изучения этих тем или для примеров, были бы очень признательны!)
Пример данных:
IN: df = pd.DataFrame(data=[[2018,10,100,50], [2018,11,110,30], [2017,12,120,10], [2017, 15, 115, 40]], columns=['Year','c1','c2','c3'])
OUT:
Year c1 c2 c3
0 2018 10 100 50
1 2018 11 110 30
2 2017 12 120 10
3 2017 15 115 40
Пример вывода:
Year c1 c2 c3 c1_std c2_std
0 2018 10 100 50 -0.707107 -0.707107
1 2018 11 110 30 0.707107 0.707107
2 2017 12 120 10 0.707107 0.707107
3 2017 15 115 40 -0.707107 -0.707107
Обратите внимание, что стандартизированный вывод предназначен только для 2 из 3 столбцов
Мой подход:
-
Сначала я создал две таблицы. Один для средних значений по столбцу и году, а также один для стандартных отклонений по столбцу и году.
standard_devs = pd.DataFrame(data=[],index=[2018,2017], columns=['c1', 'c2']) means = pd.DataFrame(data=[],index=[2018,2017], columns=['c1', 'c2']) for y in [2018,2017]: for col in ['c1', 'c2']: standard_devs.loc[y,col] = df[df['Year']==y][col].std() means.loc[y,col] = df[df['Year']==y][col].mean()
-
Я перебрал свой исходный фрейм данных и вычислил стандартизированные значения на основе соответствующего года и столбца.
for i in list(df.index): for col in ['c1', 'c2']: year = df.loc[i,'Year'] df.loc[i,col '_std'] = (df.loc[i,col]-means.loc[year, col])/standard_devs.loc[year, col]
Я читал ранее, что итерация по фрейму данных pandas является плохой практикой. Я знаю, что этот метод, вероятно, не может масштабироваться, поэтому мне было интересно, как я мог бы быть более эффективным с моим кодированием.
Спасибо вам всем!
Комментарии:
1. Пожалуйста, добавьте пример для вывода, т. Е. Какой результат вам нужен. Итерация должна быть последним средством в Pandas
2. Привет, gtomer, я добавил несколько примеров вывода.
Ответ №1:
Вы можете использовать groupby.transform
здесь для вычисления std
и mean
. Это вычислит соответствующую метрику по группе и вернет ряд с одинаковой длиной оси df
:
for c in ['c1', 'c2']:
stds = df.groupby('Year')[c].transform('std')
means = df.groupby('Year')[c].transform('mean')
df[f'{c}_std'] = (df[c] - means) / stds
Альтернативным подходом было бы временно установить ваш индекс на ваш ключ groupby:
means = df.groupby('Year')[['c1', 'c2']].mean()
stds = df.groupby('Year')[['c1', 'c2']].std()
(df.join((((df.set_index('Year') - means) / stds))
.reset_index(drop=True)
.add_suffix('_std')))
[выход]
Year c1 c2 c3 c1_std c2_std
0 2018 10 100 50 -0.707107 -0.707107
1 2018 11 110 30 0.707107 0.707107
2 2017 12 120 10 -0.707107 0.707107
3 2017 15 115 40 0.707107 -0.707107
Комментарии:
1. Привет, Крис, спасибо за твой ответ! Я должен был быть более четким в своем вопросе, но я не хочу стандартизировать каждый столбец в фрейме данных. В примере я стандартизировал только 2 из 3 столбцов. Кроме того, если бы я применил это к фрейму данных, в котором столбцы были нечисловыми, сработало бы это решение или оно потерпело бы неудачу, потому что длины результирующих фреймов данных means и stds отличались бы? Спасибо!
2. Произойдет сбой, если какой-либо из столбцов, к которым вы пытаетесь применить это, не является числовым.