【问题标题】:Breaking up (melting) text data in a column in R?在 R 的列中分解(熔化)文本数据?
【发布时间】:2013-05-21 11:18:03
【问题描述】:

我有一个 csv 文件,其中包含以下格式的数据:

PrjID目标
1001 , (i) 提高效率 (ii) 降低成本 (iii) 最大化收入
1002 , a) 玩得开心 b) 学习新事物
1003、(1)变得棘手(2)挑战任务

第一个变量是 Id,第二个变量是文本变量“objective”。每个项目在单个列中都有多个目标的数据,由 (i)、(ii)、..etc 或 (a)、(b)、(c)、..etc 或 (1)、(2) 分隔, (3),..等。现在我想要为项目的每个目标创建一个观察结果。很像这样:

PrjID目标
1001、(一)提高效率
1001 , (ii) 降低成本
1001 , (iii) 最大化收入
1002、a) 玩得开心
1002 , b) 学习新事物
1003、(1)变得棘手
1003、(2)挑战任务

对于只有一个目标的项目,它只有一行。但是对于多个目标,它会拆分观察。

我对在 R 中处理文本数据很陌生,可以请一些 R 专业人士帮助我开始解决这个问题吗?提前致谢!

【问题讨论】:

    标签: r text


    【解决方案1】:

    这里有一个想法。

    1. 使用巧妙的正则表达式在您的 Objective 列中插入新的分隔符
    2. strsplit 中使用此分隔符将句子拆分为向量
    3. 使用by,按ID处理前面的步骤。

    按照这些步骤,我得到了这个代码:

    ll <- by(dat,dat$PrjID,FUN = function(x){
            x.delim <- gsub(" (\\(?[a-x,0-9]*\\))",'#\\1',x$Objective)
            obj  = unlist(strsplit(x.delim,'#'))
            data.frame(PrjID= x$PrjID,objective=obj[-1])
    })
    ## transform your list to a data.frame
    do.call(rbind,ll)
    
          PrjID                 objective
    1001.1  1001 (i) To improve efficiency
    1001.2  1001        (ii) Decrease cost
    1001.3  1001   (iii) Maximize revenue 
    1002.1  1002               a) Have fun
    1002.2  1002      b) Learn new things 
    1003.1  1003        (1) Getting tricky
    1003.2  1003      (2) Challanging task
    

    PS,这里 dat 是:

    dat <- read.table(text='PrjID, Objective 
    1001 , (i) To improve efficiency (ii) Decrease cost (iii) Maximize revenue 
    1002 , a) Have fun b) Learn new things 
    1003 , (1) Getting tricky (2) Challanging task',sep=',',header=TRUE)
    

    【讨论】:

    • 甜美,很棒的方法!剩下要解决的唯一挑战是我们有真正的括号的情况。意思是如果我有一个像“(i)学习东西(并且做很棒的东西)”这样的目标。对此有何看法?
    • 如果您的项目只是 a,b,c 和 i 序列,您可以将正则表达式更改为 (\\(?[a,b,c,i,0-9]{1-4}\\))...
    • 完美,这正是我想要的。非常感谢agstudy!!
    【解决方案2】:

    从 agstudy 的答案中取一个叶子,这是一个不使用 magic 分隔符但不保留文本中点的索引的解决方案:

    // Matches:
    // 1. Single letter prefixes: a), b) ... z)
    // 2. Roman numerals (only small case): [i,x,c,m,v]+
    // 3. Numeral indexes: [0-9]*
    delim <- "((^|\\s)\\(?([a-z]|[i,x,c,m,v]+|[0-9]+)\\))"
    
    ll <- by(dat, dat$PrjID, function (r) {
                each.obj <- str_split(r$Objective, delim)[[1]][-1]
                data.frame(PrjId = r$PrjID, Objective = str_trim(each.obj))
            })
    
    do.call(rbind, ll)
    
           PrjId                     Objective
    1001.1  1001     First(could be something)
    1001.2  1001 Seconds (blah something else)
    1001.3  1001      (how can thins be) Third
    1002.1  1002         To improve efficiency
    1002.2  1002                 Decrease cost
    1002.3  1002              Maximize revenue
    1003.1  1003                Getting tricky
    1003.2  1003              Challanging task
    

    dat 在这种情况下是:

    > dat
      PrjID
    1  1001
    2  1002
    3  1003
                                                                                        Objective
    1 (i) First(could be something) b) Seconds (blah something else) (3) (how can thins be) Third
    2                        (i) To improve efficiency (ii) Decrease cost (iii) Maximize revenue
    3                                                     (1) Getting tricky (2) Challanging task 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-08
      • 2016-08-15
      • 2012-01-03
      • 2020-02-06
      • 1970-01-01
      相关资源
      最近更新 更多