【问题标题】:Split strings by commas only if substrings are elements of another vector仅当子字符串是另一个向量的元素时才用逗号拆分字符串
【发布时间】:2014-08-02 18:42:48
【问题描述】:

我有一组调查回复,受访者可以选择零个或多个选项来回答“您喜欢哪种水果?”这个问题。还有一个填写答案的空间。在结果电子表格中,每个人的回答都在一个单元格中,不同类型的水果用逗号分隔,如下所示:

(df <- data.frame(id = c("A", "B", "C", "D", "E"), 
                 data = c("oranges, apples, peaches, cherries, pineapples, strawberries",
                          "oranges, peaches, pears", 
                          "pears, nectarines, cherries (bing, rainier)", 
                          "apples, peaches, nectarines", 
                          ""), 
                 stringsAsFactors = FALSE))

#   id                                                         data
# 1  A oranges, apples, peaches, cherries, pineapples, strawberries
# 2  B                                      oranges, peaches, pears
# 3  C                  pears, nectarines, cherries (bing, rainier)
# 4  D                                  apples, peaches, nectarines
# 5  E  

我想要做的是将响应拆分成一个长格式的表格,我使用底部的代码几乎已经完成了。但是,一些受访者在他们的写入回复中包含逗号,我不想在逗号上拆分他们的答案。我知道所有最初的多项选择选项是什么; 我怎样才能只拆分这些答案,而让写入(带逗号)保持不变?我想最终得到一个这样的数据框:

   id                               data
1   A                            oranges
2   A                             apples
3   A                            peaches
4   A cherries, pineapples, strawberries
5   B                            oranges
6   B                            peaches
7   B                              pears
8   C                              pears
9   C                         nectarines
10  C           cherries (bing, rainier)
11  D                             apples
12  D                            peaches
13  D                         nectarines

多项选择选项是:

mc_answers <- c("oranges", "plums", "apples", "peaches", "pears", "nectarines")

到目前为止我已经完成的是:

# use strsplit to create a list of the types of fruit each person likes
datalist <- strsplit(df$data, ", ")
names(datalist) <- df$id

# remove zero-length list elements (person E doesn't like any fruit)
datalist <- Filter(length, datalist)

# convert list elements to data frames
datalist_dfs <- lapply(datalist, data.frame, stringsAsFactors = FALSE)
datalist_dfs <- lapply(datalist_dfs, setNames, "data") # name each column 'data'

# add id column to each data frame
data_long <- mapply(function(x, y) "[<-"(x, "id", value = y), datalist_dfs, 
                    names(datalist_dfs), SIMPLIFY = FALSE)

# combine into one big data frame
(data_per_person <- do.call('rbind', data_long))
#               data id
# A.1        oranges  A
# A.2         apples  A
# A.3        peaches  A
# A.4       cherries  A   # should
# A.5     pineapples  A   # be one
# A.6   strawberries  A   # entry
# B.1        oranges  B
# B.2        peaches  B
# B.3          pears  B
# C.1          pears  C
# C.2     nectarines  C
# C.3 cherries (bing  C   # should be 
# C.4       rainier)  C   # one entry
# D.1         apples  D
# D.2        peaches  D
# D.3     nectarines  D

对于一个人可以选择多少水果没有规定,但如果有一个写入答案,它总是最后一个。

【问题讨论】:

    标签: r string strsplit


    【解决方案1】:

    在这一行之后:

    datalist <- Filter(length, datalist)
    

    做:

    datalist <- lapply(datalist, function(x) {
       if(any(!x %in% mc_answers))
           c(x[x %in% mc_answers], paste(x[!x %in% mc_answers], collapse = ", "))
       else
           x[x %in% mc_answers]
    })
    

    然后按原样运行其余代码,最终得到:

    > (data_per_person <- do.call('rbind', data_long))
                                      data id
    A.1                            oranges  A
    A.2                             apples  A
    A.3                            peaches  A
    A.4 cherries, pineapples, strawberries  A
    B.1                            oranges  B
    B.2                            peaches  B
    B.3                              pears  B
    C.1                              pears  C
    C.2                         nectarines  C
    C.3           cherries (bing, rainier)  C
    D.1                             apples  D
    D.2                            peaches  D
    D.3                         nectarines  D
    

    【讨论】:

      【解决方案2】:

      你也可以试试:

       library(data.table)
       library(devtools)
       source_gist(11380733) ## 
      
       df1 <- cSplit(df, "data", sep=", ", "long")
       indx <- df1$data %in% mc_answers
       res <- rbindlist(list(df1[indx,], df1[!indx,][, list(data=paste(data, collapse=", ")), by=id]))[order(id)]
      
        res
        #   id                               data
        #1:  A                            oranges
        #2:  A                             apples
        #3:  A                            peaches
        #4:  A cherries, pineapples, strawberries
        #5:  B                            oranges
        #6:  B                            peaches
        #7:  B                              pears
        #8:  C                              pears
        #9:  C                         nectarines
       #10:  C           cherries (bing, rainier)
       #11:  D                             apples
       #12:  D                            peaches
       #13:  D                         nectarines
      

      【讨论】:

        【解决方案3】:

        这样的事情怎么样

        do.call(rbind, lapply(split(df, df$id), function(x) {
            v<-unlist(strsplit(x$data, ",\\s?"))
            v<-c(v[v %in% mc_answers], paste(v[!v %in% mc_answers], collapse=", "))
            v<-v[nchar(v)>0]
            if (length(v)>0) {
                data.frame(id=x$id[1], data=v)
            } else {
                NULL
            }
        }))
        

        这里我们拆分为分别处理每个组,然后进行字符串拆分。然后我们折叠所有不在mc_answers 向量中的条目。它返回

            id                               data
        A.1  A                            oranges
        A.2  A                             apples
        A.3  A                            peaches
        A.4  A cherries, pineapples, strawberries
        B.1  B                            oranges
        B.2  B                            peaches
        B.3  B                              pears
        C.1  C                              pears
        C.2  C                         nectarines
        C.3  C           cherries (bing, rainier)
        D.1  D                             apples
        D.2  D                            peaches
        D.3  D                         nectarines
        

        【讨论】:

          猜你喜欢
          • 2016-12-21
          • 2015-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多