pandas: присвоить значение на основе эквивалентного значения в другой строке с помощью поиска

#python #pandas

#python #pandas

Вопрос:

У меня есть фрейм данных с такой структурой:

 df = pd.DataFrame([
    { "state": "CA", region="West", "total" 2, "week": 10 },
    { "state": "UT", region="Midwest", "total" 7, "week": 10 },
    { "state": "CA", region="CA", "total" 14, "week": 11 },
    { "state": "UT", region="UT", "total" 18, "week": 11 },
    { "state": "CA", region="West", "total" 21, "week": 12 },
    { "state": "UT", region="Midwest", "total" 30, "week": 12 }
])
  

(В моем реальном наборе данных есть все состояния!)

Все region значения для строк с week установленным значением 11 были установлены неправильно, поэтому я хотел бы заменить их значением для того же состояния на неделе 10.

Я попробовал это:

 df[df.week == 11].region = df[df.week == 10].region
  

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

Ответ №1:

Предполагая, что все ваши состояния имеют недели 10 и 11, вы можете сортировать и использовать loc в качестве средства доступа к меткам для установки новых значений после соответствующей сортировки вашего фрейма. Также я исправил значения словаря для вашего фрейма данных.

 import pandas as pd

df = pd.DataFrame([
    { "state": "CA", "region":"West", "total" :2, "week": 10 },
    { "state": "UT", "region":"Midwest", "total": 7, "week": 10 },
    { "state": "CA", "region":"CA", "total" :14, "week": 11 },
    { "state": "UT", "region":"UT", "total" :18, "week": 11 },
    { "state": "CA", "region":"West", "total": 21, "week": 12 },
    { "state": "UT", "region":"Midwest", "total" :30, "week": 12 }
]).sort_values(by = ['state','week'])

df.loc[df['week'] == 11, 'region'] = df.loc[df['week'] == 10, 'region'].to_numpy()

df

>>
    state   region  total   week
0   CA  West    2   10
2   CA  West    14  11
4   CA  West    21  12
1   UT  Midwest 7   10
3   UT  Midwest 18  11
5   UT  Midwest 30  12
  

Ответ №2:

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

  1. объединить подмножество фрейма данных обратно в себя с определенными критериями, объединяющимися по состоянию и неделе (порядок не имеет значения, поскольку вы используете слияние)
  2. используйте np.where() для обновления соответствующих значений, используя новый region_x столбец для обновления region , где это уместно
  3. затем вы можете просто удалить region_x

 df = df.merge(df.loc[df['week'] == 11, ['state','region','week']].replace(10,11),
             how='left',
             on=['state', 'week'], suffixes=('', '_x'))
df['region'] = np.where(df['region'] == 11, df['region_x'], df['region'])
df = df.drop('region_x', axis=1)
  

Если вы не возражаете против сортировки вашего фрейма данных, вы также можете использовать ffill() . Убедитесь, что в вашем столбце «регион» еще нет NaN значений. В случае, если это произойдет, я включил эту строку кода: df['region'] = df['region'].replace(np.nan, 'Unknown') чтобы непреднамеренные NaN значения не заполнялись непреднамеренно, но, возможно, вам не нужна эта строка кода:

 df = df.sort_values(['state', 'week'])
df['region'] = df['region'].replace(np.nan, 'N/A') #optional
df['region'] = np.where(df['week'] == 11, np.nan, df['region'])
df['region'] = df['region'].ffill()