【问题标题】:How to collect unstructured data from a database?如何从数据库中收集非结构化数据?
【发布时间】:2014-06-17 17:25:40
【问题描述】:

我想从一个相当大的表(大约 350 000 个观察值)中收集非结构化数据。你会推荐什么策略?

假设我有以下数据库

|ID |                           Description                          | 
|12 | Mr A is thirty-five years old and works as an accountant in ...|
|34 | Mr B, 24 and has set up a retail business since 2004.          |
|55 | Mr C aged 58, lives in town A and has a hardware shop ...      |

...

我想在每次观察中获得城镇的年龄和职业。 (如果数据可用)。

我开始使用带有 Perl 类型正则表达式的 SAS。我花了很多时间构建正则表达式并捕获数据,但效果很好。我知道正则表达式可能不是最好的策略,但我想在观察次数增加时自动捕获大部分数据。

【问题讨论】:

  • 这似乎是一个自然语言处理问题,正则表达式通常不适合。让人类进行数据输入可能是最简单的解决方案。但是,您可以为数据库构建一个图形界面来帮助输入数据。
  • regex 表示输入是结构化的,或 regular
  • @amon 你能指出如何构建图形界面吗?只是一些参考就可以了。
  • @veryhungrymike,我的数据是非结构化的,但它们仍然包含一些值得利用的模式。你能用多少种方式描述一个人的年龄或职业?
  • 要构建用户界面,您可以使用 GTK 之类的原生工具包,但使用 CGI 前端构建简单的 CRUD Web 应用程序会容易得多。

标签: python regex linux perl sas


【解决方案1】:

我在这里同时看到两个问题。一:提取结构化数据。二:以图形方式呈现。我会从 One 开始。

我认为以下不是一个精确的解决方案,也不会赢得任何算法奖,并且对于 350.000 行,可能会花几个晚上运行。但如果你想尝试这条路,这可能会给你一些提示。 (但正如一些人所说,这可能是一条非常崎岖的道路,甚至是死胡同)

向表中添加几列,使用 (class) DBI 遍历行,添加单独的函数来尝试猜测每个参数。

参见例如PerlMonks 进行一些高效的数据库更新。

#meta code alert
my $dbh= DBI->new('connect to a database');
my $sth = $dbh->prepare("SELECT ID, THETEXT FROM ATABLE");
$sth->execute();
while (my $row = $sth->fetchrow_hashref) {
    my $age = guess_age($row->{TEXT});
    if ($age > 0) {
        ...#update database
    }
}
#end meta

sub guess_age{
     my $text = shift,
     my $age;
     #look for text, any sequence of number words or - or <whitespace>\s 
     if ($text =~ /((?:one|two|three|...ninety|-|\s)+)/  ) {
        $age = some_number_from_text_function($1)
     #see if we have some prefix words in front of a number 
     } elsif ($text =~ /(?:age|aged)\s*(\d+)/ ) {
        $age = $1;
     #see if we have some postfix words after a number  
     } elsif ($text =~ /(\d+)\s*(?:old|of age|years)/ ) {
        $age = $1;
     #see if we have a comma early in the sentence, 
     } elsif ($text =~ /,\s*(\d+)/ ) {
            #this 'if' should been part of main elsif, as it may stop here:-(
        if ($-[0] <50) {#found before pos 50 in the text
            $age = $1;
        }
    } elsif (... ) {
    } else {
        $age = -1; #flag : not found?
     }
     return $age;
}

但同样,这可能是一个死胡同......

对于 Town,我想任何意外的大写都可能需要寻找 /[az]\W([AZ]\w+)/#ie 一个非大写字母后跟一个非字母,然后是一个大写 +任何字母。对于职业,我真的没有线索。也许对一个有很多职业的大哈希做一个单词匹配?

【讨论】:

  • 感谢您的帮助!作为第一种方法,我只是将所有年龄的正则表达式堆叠在一起,但我不得不使用更多条件。我得到了 60% 的数据的年龄。然而,我无法测试我的数据有多精确。不过我是在 SAS 中完成的,因为我不太了解 perl。我会仔细考虑你的方法。
猜你喜欢
  • 1970-01-01
  • 2014-10-18
  • 1970-01-01
  • 2014-11-20
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
  • 2016-08-22
  • 1970-01-01
相关资源
最近更新 更多