#python #pandas #dataframe
#python #pandas #фрейм данных
Вопрос:
Я пытаюсь лучше понять Pandas / Python, поэтому я поиграл с некоторыми вещами. Я столкнулся с проблемой, я знаю некоторые обходные пути, но мне интересно, почему это произошло в первую очередь.
Вот мой полный код, за которым следует объяснение:
df1 = pd.DataFrame(np.random.rand(5, 10).round(2), index = list(range(1,6)), columns = list(range(1, 11)) )
df2 = pd.DataFrame(index = range(df1.shape[0]), columns = range(df1.shape[1]) )
df2[df1.iloc[:]>0.6] = 1
df2[df1.iloc[:]<0.6] = 0
Я создаю 2 фрейма данных. Первый со случайными числами, второй фрейм данных пуст, но имеет те же размеры, что и первый. Основываясь на значениях в первом фрейме данных, я хотел бы изменить значения во втором.
df1 = pd.DataFrame(np.random.rand(5, 10), index = list(range(1,6)), columns = list(range(1, 11)) )
Мой первый созданный мной фрейм данных выглядит так:
df1
1 2 3 4 5 6 7 8 9 10
1 0.24 0.03 0.93 0.38 0.03 0.83 0.47 0.85 0.79 0.65
2 0.66 0.25 0.01 0.28 0.19 0.26 0.25 0.48 0.33 0.92
3 0.53 0.33 0.78 0.04 0.36 0.63 0.16 0.16 0.21 0.96
4 0.76 0.03 0.89 0.15 0.24 0.90 0.59 0.41 0.92 0.98
5 0.72 0.45 0.95 0.44 0.79 0.93 0.90 0.48 0.61 0.02
Я создаю второй фрейм данных на основе измерений второго:
df2 = pd.DataFrame(index = range(df1.shape[0]), columns = range(df1.shape[1]) )
Что я хотел бы сделать сейчас, так это сказать, что для значений, которые больше 0,6 в df1, я бы хотел, чтобы соответствующее значение в df2 было равно 1. И для значений меньше 0,6 я бы хотел, чтобы значения были равны 0.
Я сделал это следующим образом, разрезав df1, а затем используя этот фрагмент для df2, а затем присвоив значения.
df2[df1.loc[:]>0.6] = 1
df2[df1.loc[:]<0.6] = 0
Я думал, что это сработает, но вместо этого первая строка и первый столбец по-прежнему являются NaNs
df2
0 1 2 3 4 5 6 7 8 9
0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 NaN 0 0 1 0 0 1 0 1 1
2 NaN 1 0 0 0 0 0 0 0 0
3 NaN 0 0 1 0 0 1 0 0 0
4 NaN 1 0 1 0 0 1 0 0 1
Я думаю, причина, по которой это не сработало, заключается в том, что имена столбцов и имена строк не совпадают между двумя индексами, но я пытаюсь понять, почему это происходит.
Я думал, что когда я нарезал df1 на основе условия, он создал массив истинных / ложных данных, который я мог бы использовать в любом другом фрейме данных с тем же измерением:
[df1.loc[:]>0.6]
r
1 2 3 4 5 6 7 8 9 10
1 False False True False False True False True True True
2 True False False False False False False False False True
3 False False True False False True False False False True
4 True False True False False True False False True True
5 True False True False True True True False True False
Я думал, что приведенное выше сопоставление истинных и ложных значений можно использовать где угодно, но, похоже, это невозможно. Есть ли способ обойти это, не требующий переименования столбцов / строк для сопоставления между 2 фреймами данных?
Ответ №1:
Просто нужно сделать:
import pandas as pd
import numpy as np
np.random.seed(42) # for reproducibility
df1 = pd.DataFrame(np.random.rand(5, 10), index = list(range(1,6)), columns = list(range(1, 11)))
df2 = df1 > 0.6
print(df2)
Выходной сигнал
1 2 3 4 5 6 7 8 9 10
1 False True True False False False False True True True
2 False True True False False False False False False False
3 True False False False False True False False False False
4 True False False True True True False False True False
5 False False False True False True False False False False
Если нужно, чтобы выходные данные были целочисленными:
df2 = (df1 > 0.6).astype(int)
print(df2)
Вывод (целое число)
1 2 3 4 5 6 7 8 9 10
1 0 1 1 0 0 0 0 1 1 1
2 0 1 1 0 0 0 0 0 0 0
3 1 0 0 0 0 1 0 0 0 0
4 1 0 0 1 1 1 0 0 1 0
5 0 0 0 1 0 1 0 0 0 0
Если необходимо сопоставить значения со значениями True и False, используйте np.где:
df2 = (df1 > 0.6)
df2[:] = np.where(df2, 'M', 'F')
print(df2)
Выход (где)
1 2 3 4 5 6 7 8 9 10
1 F M M F F F F M M M
2 F M M F F F F F F F
3 M F F F F M F F F F
4 M F F M M M F F M F
5 F F F M F M F F F F
Комментарии:
1. Что ж, черт возьми, это, кажется, приближает меня к цели. Если вы не возражаете, у меня есть несколько дополнительных вопросов. Когда я это делаю, df2 превращается в true и false, любой способ преобразовать это в 0s и 1s или любые другие 2 значения? Кроме того, я действительно хочу понять, почему способ нарезки, который я пробовал, зависит от названия столбцов и строк? Есть ли способ просто создать общий массив истинных / ложных значений, который может быть применен к любому фрейму данных независимо от имени строк или столбцов?
2. «Pandas выравнивает все ОСИ при настройке рядов и фрейма данных из .loc и .iloc». Индексирование фрейма данных с помощью оператора [] будет использовать любой доступный индекс. Фреймы данных в ваших примерах имеют разные индексы, поэтому здесь это работает как внешнее соединение SQL. pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html
3. @MSCRN обновил ответ примерами для ваших вопросов. Я не понимаю: кроме того, я действительно хочу понять, почему способ нарезки, который я пробовал, зависит от имени столбцов и строк? Есть ли способ просто создать общий массив истинных / ложных значений, который может быть применен к любому фрейму данных независимо от имени строк или столбцов?
4. @skuzzy Я думаю, что я следую, хотя я не уверен в бите внешнего соединения SQL. Итак, если я понимаю, если вы используете, .loc , .iloc или оператор [], Pandas сначала проверяет соответствие осей (столбцов и строк) на основе их имен, а не на позиции?
5. Позиция может иметь много значений. Как вы определяете позицию в фрейме данных, который может иметь много уровней / уровней? То, о чем вы думаете, — это относительные координаты. Индексы — это своего рода абсолютные координаты. В качестве примера возьмем студентов из двух университетов. Является ли первый ранг в университете 1 эквивалентным первому рангу в университете 2?
Ответ №2:
Попробуйте с np.where
помощью , обратите внимание, что здесь находится открытая ячейка, что означает, что будет возвращено значение, равное 0.6 NaN
df2[:] = np.where(df1>0.6,1,0)
df2
0 1 2 3 4 5 6 7 8 9
0 0 1 1 1 0 0 0 0 1 0
1 1 0 0 0 0 0 1 1 0 0
2 1 0 0 1 1 0 1 0 1 1
3 1 0 0 1 1 1 0 1 0 0
4 1 0 1 1 1 0 0 1 1 0
Комментарии:
1. Это невероятно элегантно, спасибо. Я не знал об этой функции numpy или о том, что вы можете использовать ее в pandas frame подобным образом.