Есть ли способ вставить пробел между символами строки в зависимости от длины, используя pandas? - PullRequest
2 голосов
/ 23 апреля 2020

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

У меня есть фрейм данных с двумя столбцами, один из которых имеет почтовые индексы, а другой - длину этих столбцов. почтовые индексы. Показано ниже:

    new_pstl_cd length
  1 SS55HA       6
  2 BD108EG      7
  3 LS15HU       6
  4 W19PX        5

Я хочу вставить пробел, чтобы столбец стал

   new_pstl_cd  
 1 SS5 5HA
 2 BD10 8EG         
 3 LS1 5HU
 4 W1 9PX

Я пробовал приведенный ниже код без успеха:

 def insert_space(charachter):
      if postcode_test['length'] == 6:
          return (postcode_test['new_pstl_cd'].str[0:3]+ charachter + postcode_test['new_pstl_cd'].str[3:])
      if postcode_test['length'] == 5:
          return (postcode_test['new_pstl_cd'].str[0:2]+ charachter + postcode_test['new_pstl_cd'].str[3:])
      else:
           return (postcode_test['new_pstl_cd'].str[0:4]+ charachter + postcode_test['new_pstl_cd'].str[4:])

Как бы я написал функцию, используя длины для этого? Обратите внимание, что в этом случае всегда будут разделяться последние 3 символа

Ответы [ 2 ]

3 голосов
/ 23 апреля 2020

вам даже не нужно length:

df['new_pstl_cd'] = df.new_pstl_cd.str[:-3] + ' ' + df.new_pstl_cd.str[-3:]

Вывод:

  new_pstl_cd  length
1     SS5 5HA       6
2    BD10 8EG       7
3     LS1 5HU       6
4      W1 9PX       5
1 голос
/ 23 апреля 2020

Проблема

Этот if / elif код, который вы пробовали, отражает распространенное заблуждение о том, как работает Pandas.

if принимает только сингл Логическое значение, т.е. True или False. postcode_test['length'] == 6 является объектом Pandas Series, т. Е. Набором many логических значений. Даже не имеет смысла использовать его в качестве входных данных для if, как объясняется в сообщении об ошибке, которое вы наверняка видели.

Вам нужно найти способ применить операцию к некоторым строкам, но не другие строки, но вы не можете использовать if. Pandas на самом деле предлагает несколько способов достижения этой цели.

Возможные решения

Как всегда, НЕ КОПИРУЙТЕ И НЕ ВСТАВЛЯЙТЕ КОД, КОТОРЫЙ ВЫ НЕ ПОНИМАЕТЕ . Обратитесь к документации библиотеки за помощью. Этот код не проверен ; он может содержать ошибки, и гарантия на него не распространяется.

Булево подмножество

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

postcode_len_6 = postcode_test['length'] == 6
postcode_len_5 = postcode_test['length'] == 5

postcode_len_6 и postcode_len_5 являются объектами Series с логическими элементами. Их элементы соответствуют элементам серии postcode_test['length'], элементы которых, в свою очередь, соответствуют строкам кадра данных postcode_test.

Вы можете использовать эти объекты серии в соответствии с указанием индексации и выбора данных :

postcode_test.loc[postcode_len_6, 'new_pstl_cd'] = \
    postcode_test.loc[postcode_len_6, 'new_pstl_cd'].str[:3] + ' '+ \
    postcode_test.loc[postcode_len_6, 'new_pstl_cd'].str[3:]

postcode_test.loc[postcode_len_5, 'new_pstl_cd'] = \
    postcode_test.loc[postcode_len_5, 'new_pstl_cd'].str[:2] + ' '+ \
    postcode_test.loc[postcode_len_5, 'new_pstl_cd'].str[2:]

Использование метода «маски»

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

Как и раньше, вы начинаете с поиска строк, длина которых равна 5 или 6:

postcode_len_6 = postcode_test['length'] == 6
postcode_len_5 = postcode_test['length'] == 5

Но вместо большого заклинание с .loc, вместо этого вы используете .mask:

postcode_test['new_pstl_cd'] = postcode_test['new_pstl_cd']\
    .mask(postcode_len_6, lambda s: s.str[:3]+' '+s.str[3:])

postcode_test['new_pstl_cd'] = postcode_test['new_pstl_cd']\
    .mask(postcode_len_5, lambda s: s.str[:2]+' '+s.str[2:])

Отображение простой функции Python

Другим решением является написание функции со скалярным значением Python это просто работает со строками.

def make_new_postcode(p):
    if len(p) == 5:
        p = p[:2] + ' ' + p[2:]
    elif len(p) == 6:
        p = p[:3] + ' ' + p[3:]
    return p

postcode_test['new_pstl_cd'] = postcode_test['new_pstl_cd'].map(make_new_postcode)

Применение простой функции Python

Вы также можете применить функцию построчно, если вы действительно хотите повторно использовать существующий "length" колонка:

def make_new_postcode(row):
    l= row['length']
    p= row['new_pstl_cd']
    if l == 5:
        p = p[:2] + ' ' + p[2:]
    elif l == 6:
        p = p[:3] + ' ' + p[3:]
    return p

postcode_test['new_pstl_cd'] = postcode_test[['length', 'new_pstl_cd']].apply(make_new_postcode, axis=1, result_type='reduce')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...