[英]Subset Columns based on partial matching of column names in the same data frame
我想了解如何通過將列名的前5個字母相互匹配來從同一數據幀中對多個列進行子集,如果它們相等,則將其子集化並將其存儲在新變量中。
這是我所需輸出的一個小解釋。 它描述如下,
可以說數據框是可以eatable
fruits_area fruits_production vegetable_area vegetable_production
12 100 26 324
33 250 40 580
66 510 43 581
eatable <- data.frame(c(12,33,660),c(100,250,510),c(26,40,43),c(324,580,581))
names(eatable) <- c("fruits_area", "fruits_production", "vegetables_area",
"vegetable_production")
我試圖編寫一個函數,它將匹配循環中的字符串,並在匹配列名稱的前5個字母后存儲子集列。
checkExpression <- function(dataset,str){
dataset[grepl((str),names(dataset),ignore.case = TRUE)]
}
checkExpression(eatable,"your_string")
上面的函數正確檢查字符串,但我很困惑如何在數據集中的列名稱之間進行匹配。
編輯: - 我認為正則表達式可以在這里工作。
你可以嘗試:
v <- unique(substr(names(eatable), 0, 5))
lapply(v, function(x) eatable[grepl(x, names(eatable))])
或者使用map()
+ select_()
library(tidyverse)
map(v, ~select_(eatable, ~matches(.)))
這使:
#[[1]]
# fruits_area fruits_production
#1 12 100
#2 33 250
#3 660 510
#
#[[2]]
# vegetables_area vegetable_production
#1 26 324
#2 40 580
#3 43 581
你想把它變成一個函數:
checkExpression <- function(df, l = 5) {
v <- unique(substr(names(df), 0, l))
lapply(v, function(x) df[grepl(x, names(df))])
}
然后簡單地使用:
checkExpression(eatable, 5)
我相信這可能會滿足您的需求:
checkExpression <- function(dataset,str){
cols <- grepl(paste0("^",str),colnames(dataset),ignore.case = TRUE)
subset(dataset,select=colnames(dataset)[cols])
}
注意在grepl
使用的模式中添加了"^"
。
使用您的數據:
checkExpression(eatable,"fruit")
## fruits_area fruits_production
##1 12 100
##2 33 250
##3 660 510
checkExpression(eatable,"veget")
## vegetables_area vegetable_production
##1 26 324
##2 40 580
##3 43 581
你的功能正是你想要的,但是有一個小錯誤:
checkExpression <- function(dataset,str){
dataset[grepl((str),names(dataset),ignore.case = TRUE)]
}
更改從obje
到dataset
集的子集的對象名稱。
checkExpression(eatable,"fr")
# fruits_area fruits_production
#1 12 100
#2 33 250
#3 660 510
checkExpression(eatable,"veg")
# vegetables_area vegetable_production
#1 26 324
#2 40 580
#3 43 581
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.