如何引用函数内变量中保存的多个列名
How to refer to multiple column names held in a variable inside a function
这来自
按照建议,我将单独发布其他请求。先码后问。
library(data.table)
# load the data
customers <- structure(list(
NAME = c("B V RAMANA ", "K KRISHNA", "B SUDARSHAN", "B ANNAPURNA ",
"BIKASH BAHADUR CHITRE", "KOTLA CHENNAMMA ", "K KRISHNA",
" B V RAMANA", "B ANNAPURNA", "ZAITOON BEE", "BIMAN BALAIAH",
" KOTLA CHENNAMMA ", "B V RAMANA"),
DOB = c("15-01-1960", "01-05-1964", "12-03-1975", "12-12-1962",
"14-05-1983", "15-07-1958", "01-05-1964", "15-01-1960",
"12-12-1962", "20-02-1960", "10-03-1964", "15-07-1958",
"15-01-1960"),
ID = c(" 502910", "502737", "502995", " 502878", "502984",
"502466", "502737", "502902 ", "502877 ", "503000",
"502979", "502467", "502902 "),
PIN = c(500033, 500050, 500032, 500084, 500032, 500032, 500084, 500035,
500084, 500084, 500032, 500032, 500032)),
.Names = c("NAME", "DOB", "ID", "PIN"),
class = c("data.table", "data.frame"), row.names = c(NA, -13L))
# function for Duplicate Key Exclusion
dupKeyEx <- function(DT, dup_cols, unique_cols) {
cols <- c(dup_cols, unique_cols)
mDT <- DT[!duplicated(DT, by=cols), .N, by=dup_cols][N > 1L]
ans <- unique(DT[mDT[, !"N"], on=dup_cols], by=cols)
setorderv(ans, c(dup_cols, unique_cols))
return(ans)
}
运行 由于 NAME
和 customers
table 中的 ID
列的开头或结尾有空格,函数得到零结果:
dup_cols <- c("NAME", "DOB")
unique_cols <- "ID"
dupKeyEx(customers, dup_cols, unique_cols)
Empty data.table (0 rows) of 4 cols: NAME,DOB,ID,PIN
所以我们trim,即删除相关列两端的空格:
library(stringr)
customers[, `:=`(NAME = str_trim(NAME),
ID = str_trim(ID))]
现在我们得到了预期的结果:
dupKeyEx(customers, dup_cols, unique_cols)
NAME DOB ID PIN
1: B ANNAPURNA 12-12-1962 502877 500084
2: B ANNAPURNA 12-12-1962 502878 500084
3: B V RAMANA 15-01-1960 502902 500035
4: B V RAMANA 15-01-1960 502910 500033
5: KOTLA CHENNAMMA 15-07-1958 502466 500032
6: KOTLA CHENNAMMA 15-07-1958 502467 500032
我想知道 dup_cols
和 unique_cols
中的列(一起分配在 dupKeyEx
函数内的 cols
变量中)是否可以 trimmed在函数本身内部。这样,在使用 dupKeyEx
函数之前,我就不需要记住 trim 相关的列了。
我进行了搜索,但无法找到在 cols
变量中引用列并在 dupKeyEx
函数中对它们应用 stringr::str_trim()
的方法。任何帮助将不胜感激。
你可以这样做:
dupKeyEx <- function(DT, dup_cols, unique_cols) {
sapply(dup_cols,function(x) DT[[x]] <<- str_trim(DT[[x]]))
cols <- c(dup_cols, unique_cols)
mDT <- DT[!duplicated(DT, by=cols), .N, by=dup_cols][N > 1L]
ans <- unique(DT[mDT[, !"N"], on=dup_cols], by=cols)
setorderv(ans, c(dup_cols, unique_cols))
return(ans)
}
或遵循@Frank 的建议,使用 data.table
语法。我们复制了table先不要修改输入:
dupKeyEx <- function(DT, dup_cols, unique_cols) {
DT<-copy(DT) # comment if you want to keep changes by reference
DT[, (dup_cols) := lapply(.SD, str_trim), .SDcols=dup_cols]
cols <- c(dup_cols, unique_cols)
mDT <- DT[!duplicated(DT, by=cols), .N, by=dup_cols][N > 1L]
ans <- unique(DT[mDT[, !"N"], on=dup_cols], by=cols)
setorderv(ans, c(dup_cols, unique_cols))
return(ans)
}
San 编辑: 以下内容很好地满足了我的目的:
dupKeyEx <- function(DT, dup_cols, unique_cols) {
cols <- c(dup_cols, unique_cols)
chr_cols <- cols[sapply(DT[, ..cols], is.character)]
DT[, (chr_cols) := lapply(.SD, stringr::str_trim), .SDcols=chr_cols]
mDT <- DT[!duplicated(DT, by=cols), .N, by=dup_cols][N > 1L]
ans <- unique(DT[mDT[, !"N"], on=dup_cols], by=cols)
setorderv(ans, c(dup_cols, unique_cols))
return(ans)
}
感谢两位贡献者。我修改了代码以仅将 str_trim
应用于字符列,以避免将其他列类型更改为字符。此更改是通过引用进行的,因为制作大型 tables 的副本会消耗包括时间在内的资源。此外,修整对我的分析工作没有不良影响 - 通常是必要的。
一般来说,在加载任何大 table 后,应立即通过以下方式修剪所有字符列:
trimCharCols <- function(DT) {
colsDT <- names(DT)
chr_cols <- colsDT[sapply(DT, is.character)]
DT[, (chr_cols) := lapply(.SD, stringr::str_trim), .SDcols=chr_cols]
}
在这种情况下,可以避免使用 dupKeyEx
函数中的两行代码。但我暂时将它们留在那里,因为我需要这个函数是 "independent".
这来自
按照建议,我将单独发布其他请求。先码后问。
library(data.table)
# load the data
customers <- structure(list(
NAME = c("B V RAMANA ", "K KRISHNA", "B SUDARSHAN", "B ANNAPURNA ",
"BIKASH BAHADUR CHITRE", "KOTLA CHENNAMMA ", "K KRISHNA",
" B V RAMANA", "B ANNAPURNA", "ZAITOON BEE", "BIMAN BALAIAH",
" KOTLA CHENNAMMA ", "B V RAMANA"),
DOB = c("15-01-1960", "01-05-1964", "12-03-1975", "12-12-1962",
"14-05-1983", "15-07-1958", "01-05-1964", "15-01-1960",
"12-12-1962", "20-02-1960", "10-03-1964", "15-07-1958",
"15-01-1960"),
ID = c(" 502910", "502737", "502995", " 502878", "502984",
"502466", "502737", "502902 ", "502877 ", "503000",
"502979", "502467", "502902 "),
PIN = c(500033, 500050, 500032, 500084, 500032, 500032, 500084, 500035,
500084, 500084, 500032, 500032, 500032)),
.Names = c("NAME", "DOB", "ID", "PIN"),
class = c("data.table", "data.frame"), row.names = c(NA, -13L))
# function for Duplicate Key Exclusion
dupKeyEx <- function(DT, dup_cols, unique_cols) {
cols <- c(dup_cols, unique_cols)
mDT <- DT[!duplicated(DT, by=cols), .N, by=dup_cols][N > 1L]
ans <- unique(DT[mDT[, !"N"], on=dup_cols], by=cols)
setorderv(ans, c(dup_cols, unique_cols))
return(ans)
}
运行 由于 NAME
和 customers
table 中的 ID
列的开头或结尾有空格,函数得到零结果:
dup_cols <- c("NAME", "DOB")
unique_cols <- "ID"
dupKeyEx(customers, dup_cols, unique_cols)
Empty data.table (0 rows) of 4 cols: NAME,DOB,ID,PIN
所以我们trim,即删除相关列两端的空格:
library(stringr)
customers[, `:=`(NAME = str_trim(NAME),
ID = str_trim(ID))]
现在我们得到了预期的结果:
dupKeyEx(customers, dup_cols, unique_cols)
NAME DOB ID PIN
1: B ANNAPURNA 12-12-1962 502877 500084
2: B ANNAPURNA 12-12-1962 502878 500084
3: B V RAMANA 15-01-1960 502902 500035
4: B V RAMANA 15-01-1960 502910 500033
5: KOTLA CHENNAMMA 15-07-1958 502466 500032
6: KOTLA CHENNAMMA 15-07-1958 502467 500032
我想知道 dup_cols
和 unique_cols
中的列(一起分配在 dupKeyEx
函数内的 cols
变量中)是否可以 trimmed在函数本身内部。这样,在使用 dupKeyEx
函数之前,我就不需要记住 trim 相关的列了。
我进行了搜索,但无法找到在 cols
变量中引用列并在 dupKeyEx
函数中对它们应用 stringr::str_trim()
的方法。任何帮助将不胜感激。
你可以这样做:
dupKeyEx <- function(DT, dup_cols, unique_cols) {
sapply(dup_cols,function(x) DT[[x]] <<- str_trim(DT[[x]]))
cols <- c(dup_cols, unique_cols)
mDT <- DT[!duplicated(DT, by=cols), .N, by=dup_cols][N > 1L]
ans <- unique(DT[mDT[, !"N"], on=dup_cols], by=cols)
setorderv(ans, c(dup_cols, unique_cols))
return(ans)
}
或遵循@Frank 的建议,使用 data.table
语法。我们复制了table先不要修改输入:
dupKeyEx <- function(DT, dup_cols, unique_cols) {
DT<-copy(DT) # comment if you want to keep changes by reference
DT[, (dup_cols) := lapply(.SD, str_trim), .SDcols=dup_cols]
cols <- c(dup_cols, unique_cols)
mDT <- DT[!duplicated(DT, by=cols), .N, by=dup_cols][N > 1L]
ans <- unique(DT[mDT[, !"N"], on=dup_cols], by=cols)
setorderv(ans, c(dup_cols, unique_cols))
return(ans)
}
San 编辑: 以下内容很好地满足了我的目的:
dupKeyEx <- function(DT, dup_cols, unique_cols) {
cols <- c(dup_cols, unique_cols)
chr_cols <- cols[sapply(DT[, ..cols], is.character)]
DT[, (chr_cols) := lapply(.SD, stringr::str_trim), .SDcols=chr_cols]
mDT <- DT[!duplicated(DT, by=cols), .N, by=dup_cols][N > 1L]
ans <- unique(DT[mDT[, !"N"], on=dup_cols], by=cols)
setorderv(ans, c(dup_cols, unique_cols))
return(ans)
}
感谢两位贡献者。我修改了代码以仅将 str_trim
应用于字符列,以避免将其他列类型更改为字符。此更改是通过引用进行的,因为制作大型 tables 的副本会消耗包括时间在内的资源。此外,修整对我的分析工作没有不良影响 - 通常是必要的。
一般来说,在加载任何大 table 后,应立即通过以下方式修剪所有字符列:
trimCharCols <- function(DT) {
colsDT <- names(DT)
chr_cols <- colsDT[sapply(DT, is.character)]
DT[, (chr_cols) := lapply(.SD, stringr::str_trim), .SDcols=chr_cols]
}
在这种情况下,可以避免使用 dupKeyEx
函数中的两行代码。但我暂时将它们留在那里,因为我需要这个函数是 "independent".