我有下面的df,其中有一个name列和class列:
df=data.frame(name=c("name1","name2","name3","name4"), class=c("classA","classA","classB","classC"))
我有下面的dataframe,其中包含名称的组合:
df2=data.frame(names=c("name1;name3","name5,name6","name2 name 8","name4"))
我需要通过执行正则表达式搜索来确定df2中名称的分类,并标记它们属于哪个类(classes),并创建一个标志(class_flag):
df2=data.frame(names=c("name1;name3","name5,name6","name2 name 8","name4"),class_flag=c("Y","N","Y","Y"),classes=c("classA,classB", NA, "classA","classC"))
我现在有一个繁琐的过程来做这件事,我将展示,但我想有一个更好的方法来做这件事,我必须为每个类做这件事,我只是为下面的一个类展示它:
class_A_search=paste(paste0("\\b",toupper(df$name),collapse = "|"))
df2%>%mutate(class_flag=ifelse(str_detect(toupper(names),class_A_search),"Y","N"), class_A=ifelse(str_detect(toupper(names),class_A_search),"classA",NA))
这是数据集的简化版本,df2有100万行,names列并不限于这里显示的那些。
2条答案
按热度按时间jhiyze9q1#
可能带有
regmatches
的基本R选项会有所帮助它给出了
q3qa4bjr2#
以下是
tidyverse
选项:如何运作
str_extract_all
返回一个列表列,每个列表元素对应于 Dataframe 中的一行。每个列表元素都是提取的正则表达式匹配的向量。1.由于
class
是一个列表列,我们使用map
来迭代它,并在deframe(df)
创建的命名向量中查找提取的值。set_names
用于在每个列表元素中创建一个命名向量,以便在步骤#4中取消嵌套(这些成为列名)。class
仍然是一个列表列。我之所以这样做,是因为R中有很多处理列表的功能,而不是将其折叠成字符串。1.使用
lengths
创建class_flag
,如果列表元素为空(例如character(0)
),则返回0(相当于FALSE
)。1.复制名为
unnest_class
的列表列class
,并将其解嵌套到列中。如果您确实需要
class
作为字符列,则可以将此输出通过管道传输到mutate(class = map_chr(class, str_flatten_comma))
。输出
基准
将
df2
中的行数增加到100,000以获得更好的性能。如果您不需要列
classA
、classB
等,并删除unnest_wider
管道,这个答案与@ThomasIsCoding发布的答案更具可比性。在没有unnest_wider
的情况下,我发现这个答案更快,但我将其保留在基准测试中,因为看起来你需要这些列: