【问题标题】:Vectorizable search of text in R dataframeR数据框中文本的矢量化搜索
【发布时间】:2014-07-05 07:06:26
【问题描述】:

我有一个数据框“cities.df”,其中一列包含巴西的所有城市,另一列包含其各自的州。

在另一个数据框“tweets.df”中,我有一列包含推文,其中可能包含有关城市或州的一些参考。

我要做的是在 tweets.df 中添加一列,并对其位置进行“估计”,假设如果他在推特上发布了有关圣保罗州某个城市的信息,那么他就位于该州圣保罗。

我是 R 新手,我能想到的唯一方法是在所有推文上使用级联循环,然后在所有城市上应用 grep 函数。但这似乎不是用 R 实现它的正确方法。

for tweet in tweets
    for city in cities
        grep(city, tweet)

我想知道是否有更“矢量化”的方式来实现这一点。

谢谢

【问题讨论】:

  • 看看expand.grid:类似sapply(expand.grid(tweets, cities), function(x, y) grep(x,y))
  • 通常希望您提供一份 MWE。这意味着您尝试过的数据和实际代码:stackoverflow.com/help/mcve

标签: r twitter dataframe


【解决方案1】:

您似乎想根据推文中提到的城市在推文中添加一列来标识州。这有几个问题。首先,城市不是唯一的——也就是说,不同州可以有多个同名城市。因此,城市并不能唯一地标识州。其次,可以通过多种方式识别城市。例如,巴西有四个不同的圣保罗,它们都可能以相同的方式被引用,尤其是在推文中。

São Paulo de Olivença
São Paulo do Potengi 
São Paulo das Missões
São Paulo 

尽管有所有这些保留,这里有一种附加城市和州名的方法。这段代码还处理了推文中提到 no 城市的可能性。

library(raster)
# this generates sample data - you have this already (??)
br   <- getData(country="BR",level=2)            # Brazil shapefile, admin level 2
# muni$NAME_1 has the state names; muni$NAME_2 has the city names
muni <- br@data                                  # ~5500 municipalities in Brazil
set.seed(1)                                      # for reproduceable example
cities <- muni[sample(1:nrow(muni),90),]$NAME_2  # 90 random cities in brazil
cities <- c(cities,rep("",10))                   # last 10% have no city mentioned
tweets <- sapply(1:100,function(i) paste("#random text",cities[i],"more random text"))

# you start here
result <- do.call(rbind,lapply(tweets,function(tweet) {
  indx <- sapply(muni$NAME_2, grepl, tweet,fixed=T) # all matching cities
  indx <- min(which(indx))                          # use only first match!!
  muni[indx,c("NAME_2","NAME_1")]                   # NAME_1 contains the state
}))
tweets <- data.frame(tweets,result)
head(tweets)
#                                                        tweets    NAME_2       NAME_1
# 1462                       #random text Piau more random text      Piau Minas Gerais
# 2048                     #random text Estiva more random text    Estiva Minas Gerais
# 1474 #random text Nova Esperança do Sudoeste more random text Esperança      Paraíba
# 4997                    #random text Monções more random text   Monções    São Paulo
# 1110                      #random text Goiás more random text     Goiás        Goiás
# 4941                    #random text Jumirim more random text   Jumirim    São Paulo
tail(tweets)
#                             tweets NAME_2 NAME_1
# NA4 #random text  more random text   <NA>   <NA>
# NA5 #random text  more random text   <NA>   <NA>
# NA6 #random text  more random text   <NA>   <NA>
# NA7 #random text  more random text   <NA>   <NA>
# NA8 #random text  more random text   <NA>   <NA>
# NA9 #random text  more random text   <NA>   <NA>

这个输出说明了另一个问题:Esperança 匹配,即使提到的实际城市是Nova Esperança do Sudoeste(它处于不同的状态......)。我没有看到解决此问题的简单方法。

【讨论】:

    【解决方案2】:

    这是您可以做到的一种方法。将citiestweets 视为从它们各自的数据帧中提取的向量。这些推文显然是虚构的,甚至不是文字。我只是通过采样字母并将它们粘贴在一起来创建它们。如果您添加一些数据,将进行更新。

    最后一行将返回包含 cities 列表中的城市的推文。

    > cities
    # [1] "Belém"               "Belo Horizonte"      "Blumenau"           
    # [4] "Brasília"            "Campinas"            "Curitiba"           
    # [7] "Florianópolis"       "Fortaleza"           "Goiania"            
    # [10] "Macáe"               "Manaus"              "Niteroi"            
    # [13] "Porto Alegre"        "Recife"              "Rio de Janeiro"     
    # [16] "Roraima"             "Salvador"            "Santo Andre"        
    # [19] "Santos"              "São José dos Campos" "São Paulo"          
    # [22] "Vitória"            
    > tweets
    # [1] "Niteroi rjzzfbymh wj fa elxbmyfk logeb"
    # [2] "no city present in this sentence"      
    # [3] "Vitória zl qxllds buoo fvclizxv zqf"   
    # [4] "Rio de Janeiro n zaocj u ouo bck"      
    # [5] "no city present in this sentence"      
    > unlist(sapply(seq(cities), function(i){
          grep(cities[i], tweets, value = TRUE)
      }))
    # [1] "Niteroi rjzzfbymh wj fa elxbmyfk logeb"
    # [2] "Rio de Janeiro n zaocj u ouo bck"      
    # [3] "Vitória zl qxllds buoo fvclizxv zqf"   
    

    【讨论】:

    • 这就是我想要的。谢谢!
    • @user2402105,如果此答案或任何其他答案对您有用,请考虑接受它作为答案。您还可以从接受答案中受益,而不仅仅是回答的人。
    【解决方案3】:

    好吧,您不需要对两者都进行迭代。 grep 一次只能采用一种模式,但可以很好地在向量中搜索结果。所以

    for city in cities
        grep(city, tweets)
    

    比较合理。

    【讨论】:

    • 嗯,没错,对向量进行 grep 会返回单词出现的索引,对吧?
    • @user2402105 确实如此。见grep("a", c("apple","lemon","banana"))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-11
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-30
    相关资源
    最近更新 更多