繁体   English   中英

如何基于观察值的单元格具有多个用逗号分隔的值来对r中的数据帧进行子集化?

[英]How to subset a dataframe in r based on an observation whose cell has more than one value separated by commas?

我对R和程序设计还算陌生,所以请多多包涵。

我有一个非常大的数据集(100,000多个观测值)。 我想基于一个特定列上的值对该数据集进行子集化。 我面临的问题是,我关注的列中的各个单元格可以一次采用多个值,并以逗号分隔。 例如说我有一个数据集“ m”:

row1<-c('1','Jon,Ryan,Lilly','Soccer','3')
row2<-c('2','Carol,Ben,Peter','Soccer','6')
row3<-c('3','Ben,Carol,Billy','Soccer','5')
row4<-c('4','Felix,Jon,Casper','Soccer','3')

m<-rbind(row1,row2,row3,row4)
colnames(m)<-c('ID','Name','Event','Duration')
rownames(m)<-c(1,2,3,4)

print(m)

  ID    Name     Event    Duration
1 "1" "Jon,Ryan, Lilly"    "Soccer" "3"     
2 "2" "Carol, Ben, Peter"  "Soccer" "6"     
3 "3" "Ben, Carol, Billy"  "Soccer" "5"     
4 "4" "Felix, Jon, Casper" "Soccer" "3" 

如何对“ m”进行子集处理,以使R仅返回“名称”列等于“ Jon”的观测值。 我试过了

subset(data, Name=='Jon') 

但这只会返回“ Jon”是列出的唯一名称的字段。 我知道使用colsplit可以从这些不同的元素创建新的列,但是某些单元格具有不同数量的列,有些单元格具有10多个元素,并且所有单元格中共有100多个不同的唯一名称。 他们在R中的命令是否可以基于名称字符串的“子集”进行子集设置? 和子集函数一样简单,但也查询字符串的一部分。 预先感谢大家的帮助!

您可以使用此代码搜索Jon并返回一个布尔值。

m.df <- as.data.frame(m)
m.df$Name <- as.character(m.df$Name)
m.df$new <- str_detect(m.df$Name, "Jon")

> m.df
  ID             Name  Event Duration   new
1  1   Jon,Ryan,Lilly Soccer        3  TRUE
2  2  Carol,Ben,Peter Soccer        6 FALSE
3  3  Ben,Carol,Billy Soccer        5 FALSE
4  4 Felix,Jon,Casper Soccer        3  TRUE

回应评论

这是一种搜索多个名称列的技巧。 合并要搜索的列,然后在组合列上使用相同的代码。

假设您还有另一列NameName-

m.df$combo <- paste(m.df$Name, m.df$NameTwo, sep = ",")
m.df$new <- str_detect(m.df$combo, "Jon")

在名称列表中放置搜索的名称有4种不同的可能性:

  1. 它是名称列表中的唯一名称
  2. 它是名称列表中多个名称中的第一个
  3. 它是名称列表中多个名称的最后一个
  4. 它在名称列表的中间

因此,如果您在任何特定位置,都可以将grepl与匹配名称的匹配字符串一起使用:

Name  <-  c("Jon,Ryan, Lilly",
            "Carol, Ben, Peter",
            "Ben, Carol, Billy",
            "Felix, Jon, Casper")

grepl('(^\\s*Jon,)|(,\\s*Jon,)|(,\\s*Jon\\s*$)|(^\\s*Jon\\s*$)',Name)
#> [1]  TRUE FALSE FALSE  TRUE

您可以这样概括:

includesName <- function(name,x)
    grepl(paste0('(^\\s*',name,',)|(,\\s*',name,',)|(,\\s*',name,'\\s*$)|(^\\s*',name,'\\s*$)'),
          x)
includesName('Jon',Name)
#> [1]  TRUE FALSE FALSE  TRUE

\\ s的使用是为了允许在名称之间或列表的末尾包含空格(特别是如果这些数据存储在具有固定宽度字符列的数据库中,或者是手工的话)输入)。

明确匹配每个方案的原因是(而不是"(Jon$)|(Jon,)"是要匹配全名,因此当您不是故意匹配时,不要意外匹配“ Ron Jon”。

对于dplyr来说 ,这是一项艰巨的任务,尤其是考虑到实际数据的大小。 我为您的m创建一个tbl_df ,它基本上是一个data.frame。 自从您问了这件事以来,我包括了第二个基于名称的变量。 我创建了一个自定义函数来搜索字符串Jon 然后使用mutate_each()在名称变量中进行搜索,然后对结果进行过滤以仅返回匹配的行。

library(dplyr)
library(stringr)

m <- data_frame(Name1 = c('Jon,Ryan,Lilly', 'Carol,Ben,Peter',
                         'Ben,Carol,Billy', 'Felix,Jon,Casper'),
                Name2 = c('Susie,Jenny,Katy', 'Nigel,Ian,Jon',
                          'Nigel, Jenny', 'Ryan, Lilly, Ben'),
                Event = 'Soccer',
                Duration = c(3, 6, 5, 3))
m
# Source: local data frame [4 x 4]

#              Name1            Name2  Event Duration
# 1   Jon,Ryan,Lilly Susie,Jenny,Katy Soccer        3
# 2  Carol,Ben,Peter    Nigel,Ian,Jon Soccer        6
# 3  Ben,Carol,Billy     Nigel, Jenny Soccer        5
# 4 Felix,Jon,Casper Ryan, Lilly, Ben Soccer        3

jon_fun <- function(x) str_detect(x, '\\bJon\\b')

m %>%
  mutate_each(funs(jon_fun), jon1 = Name1, jon2 = Name2) %>%
  filter(jon1 | jon2) %>%
  select(-starts_with('jon'))
# Source: local data frame [3 x 4]

#              Name1            Name2  Event Duration
# 1   Jon,Ryan,Lilly Susie,Jenny,Katy Soccer        3
# 2  Carol,Ben,Peter    Nigel,Ian,Jon Soccer        6
# 3 Felix,Jon,Casper Ryan, Lilly, Ben Soccer        3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM