Выполнить итерацию по фрейму данных pandas и заменить некоторые строки числами

#pandas #dataframe #replace

#pandas #фрейм данных #заменить

Вопрос:

У меня есть sample_df фрейм данных, который выглядит как:

      bar   foo
0    rejected unidentified
1    clear    caution
2    caution    NaN
 

Обратите внимание, что это всего лишь случайный составленный df, есть много других столбцов, скажем, с разными типами данных, а не только с текстом. bar и foo также могут содержать много пустых ячеек / значений, которые являются NaN.

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

 |      |   Unnamed: 0 | user_id                          | result   | face_comparison_result   | created_at          | facial_image_integrity_result   | visual_authenticity_result   | properties      | attempt_id                       |
|-----:|-------------:|:---------------------------------|:---------|:-------------------------|:--------------------|:--------------------------------|:-----------------------------|:----------------|:---------------------------------|
|    0 |           58 | ecee468d4a124a8eafeec61271cd0da1 | clear    | clear                    | 2017-06-20 17:50:43 | clear                           | clear                        | {}              | 9e4277fc1ddf4a059da3dd2db35f6c76 |
|    1 |           76 | 1895d2b1782740bb8503b9bf3edf1ead | clear    | clear                    | 2017-06-20 13:28:00 | clear                           | clear                        | {}              | ab259d3cb33b4711b0a5174e4de1d72c |
|    2 |          217 | e71b27ea145249878b10f5b3f1fb4317 | clear    | clear                    | 2017-06-18 21:18:31 | clear                           | clear                        | {}              | 2b7f1c6f3fc5416286d9f1c97b15e8f9 |
|    3 |          221 | f512dc74bd1b4c109d9bd2981518a9f8 | clear    | clear                    | 2017-06-18 22:17:29 | clear                           | clear                        | {}              | ab5989375b514968b2ff2b21095ed1ef |
|    4 |          251 | 0685c7945d1349b7a954e1a0869bae4b | clear    | clear                    | 2017-06-18 19:54:21 | caution                           | clear                        | {}              | dd1b0b2dbe234f4cb747cc054de2fdd3 |
|    5 |          253 | 1a1a994f540147ab913fcd61b7a859d9 | clear    | clear                    | 2017-06-18 20:05:05 | clear                           | clear                        | {}              | 1475037353a848318a32324539a6947e |
|    6 |          334 | 26e89e4a60f1451285e70ca8dc5bc90e | clear    | clear                    | 2017-06-17 20:21:54 | suspected                           | clear                        | {}              | 244fa3e7cfdb48afb44844f064134fec |
|    7 |          340 | 41afdea02a9c42098a15d94a05e8452b | NaN    | clear                    | 2017-06-17 20:42:53 | clear                           | clear                        | {}              | b066a4043122437bafae3ddcf6c2ab07 |
|    8 |          424 | 6cf6eb05a3cc4aabb69c19956a055eb9 | rejected    | NaN                    | 2017-06-16 20:00:26 | 
 

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

 def no_strings(df):
  columns=list(df)
  for column in columns:
    df[column] = df[column].map(result_map)
#We will need a mapping of strings to numbers to be able to analyse later.
result_map = {'unidentified':0,"clear": 1, 'suspected': 2,"caution" : 3, 'rejected':4}
 

Таким образом, результат может выглядеть следующим образом:

   bar  foo
0    4    0
1    1    3
2    3    NaN
 

По какой-то причине при запуске no_strings(sample_df) я получаю ошибки.

Что я делаю не так?

Комментарии:

1. Можете ли вы показать нам пример df и ожидаемый результат

2. Конечно, отредактировал.

Ответ №1:

 df['bar'] = df['bar'].map(result_map)
df['foo'] = df['foo'].map(result_map)
 

df

     bar foo
0   4   0
1   1   3
2   3   2
 

Однако, если вы хотите быть в безопасности (предполагая, что ключа / значения нет в вашей result_map, и вы не хотите видеть NaN), сделайте это:

 df['foo'] = df['foo'].map(lambda x: result_map.get(x, 'not found'))
df['bar'] = df['bar'].map(lambda x: result_map.get(x, 'not found'))
 

итак, вывод для этого df

     bar           foo
0   rejected      unidentified
1   clear         caution
2   caution       suspected
3   sdgdg         0000
 

приведет к:

    bar              foo
0   4                0
1   1                3
2   3                2
3   not found        not found
 

Для большей эффективности:

 cols = ['foo','bar','other_columns']
for c in cols:
   df[c] = df[c].map(lambda x: result_map.get(x, 'not found'))
 

Комментарии:

1. Спасибо! Можете ли вы редактировать, когда вы просто хотите перебирать столбцы и не знаете, что они называются foo или bar? Итак, вы просто хотите, чтобы функция вносила изменения в каждую ячейку, которую вы видите, Которая содержит четкие, неопознанные и т. Д., И оставляла существующие ячейки неизменными?

2. @DhruvGhulati я добавил это в сообщение. См. Раздел «для большей эффективности» 😉

3. Это работает! Только одно, это не оставляет существующие ячейки неизменными. если он находит NaN, он заменяет его на not found, но если ячейка содержит что-то вроде 8190909e566647a5b6afeee9b4ec6c6a, по какой-то причине она превращается в «не найдена». не найдено должно быть только для пробелов или существующих NAN, которые были преобразованы через np.nan

Ответ №2:

Давайте попробуем stack, сопоставим dict и затем разархивируем

 df.stack().to_frame()[0].map(result_map).unstack()



    bar  foo
0    4    0
1    1    3
2    3    2
 

Комментарии:

1. Извините, sample_df=sample_df.stack().to_frame()[0].map(result_map).unstack() тогда я пишу display(sample_df) . Все, что я вижу, это увеличение NAN и 0.

2. Хорошо, помогает ли это df.drop(columns=cols).join(df.filter(items=cols).apply(lambda x: x.map(result_map))) , где cols находятся столбцы, которые вам нужно перенести в сопоставления.