是否存在R或Python函数,用于将信息以不定界的字符串分隔开(信息随处变化)?

时间:2019-08-27 07:34:47

标签: python r

我目前正在清理一个凌乱的数据表,在一个Excel单元格中给出信息,该单元格中不区分不同的特征(没有逗号,空格是随机的)。 因此,我的问题是要分隔不同的信息,而不能在代码中使用分隔符(不能使用split命令)

我假设我需要包括信息各部分的某些特征,以便识别相应的特征。但是,我不知道如何执行此操作,因为我是Python的新手,我只在回归模型和其他统计分析的框架中使用R。

短数据示例: 输入:

"WMIN CBOND12/05/2022 23554132121"

“ WalMaInCBND 12/05 / 2022-23554132121”

“ WalmartI CorpBond12 / 05/2022 | 23554132121”

预期输出:

"Walmart Inc.", "Corporate Bond", "12/05/2022", "23554132121"

因此,每个“ x”都应在新列中分类,并带有相应的标题(公司,安全性,到期日,帐号)

您可以看到输入是随机变化的,但是我希望上面给出的三个输入中的每个输入都具有相同的输出(我拥有超过20万个数据点,分别来自不同的公司,证券等)

第一个问题是如何在不使用系统模式的情况下有效地分离信息。

第二个问题(优先级较低)是如何识别公司,而无需为50k公司设置具有50种不同输入的字典。

感谢您的帮助!

4 个答案:

答案 0 :(得分:0)

修改

s = c("WMIN CBOND12/05/2022 23554132121",
      "WalMaInCBND 12/05/2022-23554132121",
      "WalmartI CorpBond12/05/2022|23554132121")


ID = gsub("([a-zA-Z]+).*","\\1",s)
ID2 = gsub(".* ([a-zA-Z]+).*","\\1",s)
date = gsub("[a-zA-Z ]+(\\d+\\/\\d+\\/\\d+).*","\\1",s)
num = gsub("^.*[^0-9](.*$)","\\1",s)

data.frame(ID=ID,ID2=ID2,date=date,num=num,stringsAsFactors=FALSE)

           ID                                ID2       date         num
1        WMIN                              CBOND 12/05/2022 23554132121
2 WalMaInCBND WalMaInCBND 12/05/2022-23554132121 12/05/2022 23554132121
3    WalmartI                           CorpBond 12/05/2022 23554132121

适用于情况1和3,但是我还没有弄清楚第二种情况的逻辑,如果不将包含公司和安全性的字符串分开,我们如何知道在何处分割呢?

答案 1 :(得分:0)

使用python和正则表达式:

import re

def make_filter(pattern):
    pattern = re.compile(pattern)
    def filter(s):
        filtered = pattern.match(s)
        return filtered.group(1), filtered.group(2), filtered.group(3), filtered.group(4)
    return filter

filter = make_filter("^([a-zA-Z]+)\s([a-zA-Z]+)(\d+/\d+/\d+)\s(\d+)$")

filter("WMIN CBOND12/05/2022 23554132121")

make_filter函数只是一个允许您修改模式的实用程序。它返回一个函数,该函数将根据该模式过滤输出。我将其与"^([a-zA-Z]+)\s([a-zA-Z]+)(\d+/\d+/\d+)\s(\d+)$"模式一起使用,该模式考虑了一些文本,一个空格,一些文本,一个日期,一个空格和一个数字。如果要整理此模式,请提供有关它的更多信息。输出将为("WMIN", "CBOND", "12/05/2022", "23554132121")

答案 2 :(得分:0)

我建议首先尽可能引入有用的分隔符,并构造一个替换字典以使用正则表达式进行处理。

import re
s = 'WMIN CBOND12/05/2022 23554132121'

# CAREFUL this not a real date regex, this should just
# illustrate the principle of regex
# see https://stackoverflow.com/a/15504877/5665958 for
# a good US date regex
date_re = re.compile('([0-9]{2}/[0-9]{2}/[0-9]{4})')

# prepend a whitespace before the date
# this is achieved by searching the date within the string
# and replacing it with itself with a prepended whitespace
# /1 means "insert the first capture group", which in our
# case is the date
s = re.sub(date_re, r' \1', s)

# split by one or more whitespaces and insert
# a seperator (';') to make working with the string
# easier
s = ';'.join(s.split())

# build a dictionary of replacements
replacements = {
    'WMIN': 'Walmart Inc.',
    'CBOND': 'Corporate Bond',
}

# for each replacement apply subsitution
# a better, but more replicated solution for
# this is given here:
# https://stackoverflow.com/a/15175239/5665958
for pattern, r in replacements.items():
    s = re.sub(pattern, r, s)

# use our custom separator to split the parts
out = s.split(';')
print(out)

答案 3 :(得分:0)

欢迎光临!是的,我们当然需要查看更多示例,而正则表达式似乎是要走的路...但是由于似乎没有结构,所以我认为最好将其视为单独的步骤。

  1. 我们知道日期为(X)X/(X)X/XXXX(例如,一两位数的日期,一两位数的月份,四位数的年份,可能带有或不带有斜杠,对吗?),然后是数字。因此,首先解决该部分,仅保留前两个类别。这实际上是简单的部分:),但不要灰心!
  2. 如果这两个类别可能没有ANY分隔符(例如WMINCBOND 12/05/202223554132121,或者分隔符并不总是例如IMAGINARY COMPANY X CBOND的分隔符,那么您就陷入了麻烦。:)但是,这就是我们可以做:
    1. 收集所有代码的列表(希望您有)。
    2. 在每个代码上使用str_detect(),看看是否可以识别任何数据集中的确切字符串(如果确实有代码lemme,我将编写代码来完成这一部分)。
  3. 识别代码后剩下的就是CBOND,不管是什么……最后做那部分……字符串的剩下就是那个。另外,如果您拥有str_detect()的所有内容列表,则可以使用相同的CBOND
  4. 只有在确定所有内容之后,您才可以替换其所代表的代码。 如果您有代码列表,请告诉我,我将发布代码。