【问题标题】:Convert decimal to Roman numerals将十进制转换为罗马数字
【发布时间】:2017-11-14 10:21:11
【问题描述】:
d_hsp={"1":"I","2":"II","3":"III","4":"IV","5":"V","6":"VI","7":"VII","8":"VIII",
       "9":"IX","10":"X","11":"XI","12":"XII","13":"XIII","14":"XIV","15":"XV",
       "16":"XVI","17":"XVII","18":"XVIII","19":"XIX","20":"XX","21":"XXI",
       "22":"XXII","23":"XXIII","24":"XXIV","25":"XXV"}
HSP_OLD['tryl'] = HSP_OLD['tryl'].replace(d_hsp, regex=True)

HSP_OLD 是一个数据框,trylHSP_OLD 的一列,下面是tryl 中的一些值示例:

SAF/HSP: Secondary diagnosis E code 1

SAF/HSP: Secondary diagnosis E code 11

我用字典代替,1-10有效,11就变成“II”,12就变成“III”。

【问题讨论】:

  • 标题似乎与代码相反。

标签: python regex pandas dictionary replace


【解决方案1】:

抱歉,没有注意到您不仅在更新字段,而且实际上希望在最后替换一个数字,但即使是这种情况 - 将数字正确转换为罗马数字要好得多映射所有可能出现的此类事件(如果数字大于 25,您的代码会发生什么情况?)。所以,这是一种方法:

ROMAN_MAP = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'),
             (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

def romanize(data):
    if not data or not isinstance(data, str):  # we know how to work with strings only
        return data
    data = data.rstrip()  # remove potential extra whitespace at the end
    space_pos = data.rfind(" ")  # find the last space before the number
    if space_pos != -1:
        try:
            number = int(data[space_pos + 1:])  # get the number at the end
            roman_number = ""
            for i, r in ROMAN_MAP:  # loop-reduce substitution based on the ROMAN_MAP
                while number >= i:
                    roman_number += r
                    number -= i
            return data[:space_pos + 1] + roman_number  # put everything back together
        except (TypeError, ValueError):
            pass  # couldn't extract a number
    return data

所以现在如果我们将您的数据框创建为:

HSP_OLD = pd.DataFrame({"tryl": ["SAF/HSP: Secondary diagnosis E code 1",
                                 None,
                                 "SAF/HSP: Secondary diagnosis E code 11",
                                 "Something else without a number at the end"]})

我们不能轻松地将我们的函数应用于整个列:

HSP_OLD['tryl'] = HSP_OLD['tryl'].apply(romanize)

结果:

                                         tryl
0       SAF/HSP: Secondary diagnosis E code I
1                                        None
2      SAF/HSP: Secondary diagnosis E code XI
3  Something else without a number at the end

当然,您可以根据需要调整romanize() 函数来搜索字符串中的任何数字并将其转换为罗马数字——这只是一个如何快速找到字符串末尾数字的示例。

【讨论】:

  • 我喜欢你的回答,但我认为如果没有这条线,它也会起作用:while number > 0: # loop-reduce while converting our number to roman numerals
  • @Zack - 你是绝对正确的,它可能从我第一次处理这个问题开始就一直存在,我忘记删除残留循环。谢谢指正。
【解决方案2】:

您需要保持项目的顺序,并从最长的子字符串开始搜索。

您可以在此处使用OrderDict。要初始化它,请使用元组列表。您可以在初始化时在此处反转它,但您也可以稍后再做。

import collections
import pandas as pd
# My test data    
HSP_OLD = pd.DataFrame({'tryl':['1. Text', '11. New Text', '25. More here']})

d_hsp_lst=[("1","I"),("2","II"),("3","III"),("4","IV"),("5","V"),("6","VI"),("7","VII"),("8","VIII"), ("9","IX"),("10","X"),("11","XI"),("12","XII"),("13","XIII"),("14","XIV"),("15","XV"), ("16","XVI"),("17","XVII"),("18","XVIII"),("19","XIX"),("20","XX"),("21","XXI"), ("22","XXII"),("23","XXIII"),("24","XXIV"),("25","XXV")]
d_hsp = collections.OrderedDict(d_hsp_lst)  # Creating the OrderedDict
d_hsp = collections.OrderedDict(reversed(d_hsp.items())) # Here, reversing

>>> HSP_OLD['tryl'] = HSP_OLD['tryl'].replace(d_hsp, regex=True)
>>> HSP_OLD
             tryl
0         I. Text
1    XI. New Text
2  XXV. More here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-09
    • 2011-10-25
    相关资源
    最近更新 更多