Отфильтруйте строку pandas, если она значительно больше соседей, учитывая, что она начинается с определенного символа

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

                        Name  Year      Value
0                     Mexico  1961      14357
1                     Mexico  1961      15161
2                     Mexico  1961     514658
3                     Mexico  1962      15559
4   United States of America  1977    2191197
5   United States of America  1978    2470734
6   United States of America  1978   52470734
7   United States of America  1979    2737377
8   United States of America  1979   52731457
9   United States of America  1980    3029030
10  United States of America  1980   53024589
11  United States of America  1981    3272565
12  United States of America  2010   15199150
13  United States of America  2010  515543018
14  United States of America  2011   15861873
15  United States of America  2011   16250364

Я хочу преобразовать его в:

                        Name  Year     Value
0                     Mexico  1961     14357
1                     Mexico  1961     15161
2                     Mexico  1961     14658
3                     Mexico  1962     15559
4   United States of America  1977   2191197
5   United States of America  1978   2470734
6   United States of America  1978   2470734
7   United States of America  1979   2737377
8   United States of America  1979   2731457
9   United States of America  1980   3029030
10  United States of America  1980   3024589
11  United States of America  1981   3272565
12  United States of America  2010  15199150
13  United States of America  2010  15543018
14  United States of America  2011  15861873
15  United States of America  2011  16250364

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

например, для Мексики в 3-й строке 514658 заменяется на 14658, во-первых, потому что 514658 значительно (5x-10x) больше, чем его соседи, то есть 15161 и 15559. Аналогично для США,

United States of America,1979,52731457

заменяется на

United States of America,1979,2731457

Сходным образом

  • United States of America,1978,52470734

  • United States of America,1980,53024589

  • United States of America,2010,515543018

заменяются на

  • United States of America,1978,2470734

  • United States of America,1980,3024589 и

  • United States of America,2010,15543018 соответственно.

Но заметьте,

  • во-первых, первый столбец, т.е. Name, должен точно совпадать,
  • во-вторых, последний столбец, т.е. Value, должен начинаться с 5 и
  • наконец, Value должен быть значительно больше, т. е. в основном на одну цифру больше, чем у соседей, чтобы избежать риска удаления ложных срабатываний.

Возможно, вы уже поняли, что это упражнение по очистке данных, в котором некоторые символы $ записаны как 5 и, следовательно, должны быть исправлены.

🤔 А знаете ли вы, что...
Python является интерпретируемым языком программирования.


3
51
1

Ответ:

Решено

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

Поэтому создайте столбцы отставания и опережения, сгруппированные по странам, используя pandas.DataFrame.shift(), а затем создайте логическую маску значений для замены, где:

  1. Значение начинается с 5.
  2. Значение как минимум в 5 раз больше предыдущего или следующего значения.

Конечно, если у вас есть страны только с одной записью, это не заменит никаких значений для этой страны.

df['lag'] = df.groupby('Name')['Value'].shift(1)
df['lead'] = df.groupby('Name')['Value'].shift(-1)
replace_val = (
    df['Value'].astype(str).str.startswith('5') & 
    (
        (df['Value'] > df['lag'] * 5) |
        (df['Value'] > df['lead'] * 5)
    )
)
df.loc[replace_val, 'Value'] = df.loc[replace_val, 'Value'].astype(str).str[1:].astype(int)
df.drop(["lag", "lead"], axis = 1, inplace=True)

Выход:

                        Name  Year     Value
0                     Mexico  1961     14357
1                     Mexico  1961     15161
2                     Mexico  1961     14658
3                     Mexico  1962     15559
4   United States of America  1977   2191197
5   United States of America  1978   2470734
6   United States of America  1978   2470734
7   United States of America  1979   2737377
8   United States of America  1979   2731457
9   United States of America  1980   3029030
10  United States of America  1980   3024589
11  United States of America  1981   3272565
12  United States of America  2010  15199150
13  United States of America  2010  15543018
14  United States of America  2011  15861873
15  United States of America  2011  16250364

Данные

data = {
    "Name": [ "Mexico", "Mexico", "Mexico", "Mexico", "United States of America", "United States of America", "United States of America", "United States of America", "United States of America", "United States of America", "United States of America", "United States of America", "United States of America", "United States of America", "United States of America", "United States of America" ],
    "Year": [ 1961, 1961, 1961, 1962, 1977, 1978, 1978, 1979, 1979, 1980, 1980, 1981, 2010, 2010, 2011, 2011 ],
    "Value": [ 14357, 15161, 514658, 15559, 2191197, 2470734, 52470734, 2737377, 52731457, 3029030, 53024589, 3272565, 15199150, 515543018, 15861873, 16250364 ]
}

df = pd.DataFrame(data)