如何根据其单元格具有多个以逗号分隔的值的观察来对 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 仅 returns 个名称列等于 'Jon' 的观察值。我试过了
subset(data, Name=='Jon')
但只有 returns 个字段,其中 'Jon' 是唯一列出的名称。我知道使用 reshape 中的 colsplit
可以从这些不同的元素创建一个新列,但有些单元格具有不同数量的列,有些单元格有超过 10 个元素,并且所有单元格中总共有超过 100 个不同的唯一名称。他们是 R 中的一个命令,可以基于名称字符串的 'subset' 进行子集化吗?像 subset 函数一样简单的东西,但它也查询字符串的一部分。预先感谢大家的帮助!
您要搜索的姓名在姓名列表中的位置有 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'的使用是允许白色 space 可以包含在名称之间或列表的末尾(特别是如果这些数据存储在具有固定宽度字符的数据库中列,或者在手动输入的情况下)。
显式匹配每个场景的原因是(而不是 "(Jon$)|(Jon,)"
是为了匹配全名,这样你就不会无意中匹配到 "Ron Jon"。
您可以使用此代码和 return 布尔值搜索 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
正在回复评论
这是搜索多个名称列的技巧。组合任意多的列来搜索,然后在组合列上使用相同的代码。
假设您还有一个名为 NameTwo 的列 -
m.df$combo <- paste(m.df$Name, m.df$NameTwo, sep = ",")
m.df$new <- str_detect(m.df$combo, "Jon")
这对 dplyr 来说是一项艰巨的任务,尤其是考虑到您的真实数据的大小。我为你的 m
创建了一个 tbl_df
,它基本上是一个 data.frame。我包括第二个基于名称的变量,因为你问过这个。我创建了一个自定义函数来搜索字符串 Jon
。然后使用 mutate_each()
在名称变量中搜索,然后将结果过滤为 return 仅匹配的行。
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
我对 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 仅 returns 个名称列等于 'Jon' 的观察值。我试过了
subset(data, Name=='Jon')
但只有 returns 个字段,其中 'Jon' 是唯一列出的名称。我知道使用 reshape 中的 colsplit
可以从这些不同的元素创建一个新列,但有些单元格具有不同数量的列,有些单元格有超过 10 个元素,并且所有单元格中总共有超过 100 个不同的唯一名称。他们是 R 中的一个命令,可以基于名称字符串的 'subset' 进行子集化吗?像 subset 函数一样简单的东西,但它也查询字符串的一部分。预先感谢大家的帮助!
您要搜索的姓名在姓名列表中的位置有 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'的使用是允许白色 space 可以包含在名称之间或列表的末尾(特别是如果这些数据存储在具有固定宽度字符的数据库中列,或者在手动输入的情况下)。
显式匹配每个场景的原因是(而不是 "(Jon$)|(Jon,)"
是为了匹配全名,这样你就不会无意中匹配到 "Ron Jon"。
您可以使用此代码和 return 布尔值搜索 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
正在回复评论
这是搜索多个名称列的技巧。组合任意多的列来搜索,然后在组合列上使用相同的代码。
假设您还有一个名为 NameTwo 的列 -
m.df$combo <- paste(m.df$Name, m.df$NameTwo, sep = ",")
m.df$new <- str_detect(m.df$combo, "Jon")
这对 dplyr 来说是一项艰巨的任务,尤其是考虑到您的真实数据的大小。我为你的 m
创建了一个 tbl_df
,它基本上是一个 data.frame。我包括第二个基于名称的变量,因为你问过这个。我创建了一个自定义函数来搜索字符串 Jon
。然后使用 mutate_each()
在名称变量中搜索,然后将结果过滤为 return 仅匹配的行。
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