经过一段时间的搜索,我找不到一个优雅的解决方案(通常是迂腐的答案,比如"只是对它进行矢量化"这可能不会一直适用),所以我想我是&#39 ;问。
简单的问题是: 我需要循环2个控制变量。 (这是通常会问的问题,并简单回答)
我遇到的真实(特定)问题可能不适用于所有人(寻找这类问题的答案)是: 我有一个数据框。让我们说它的工资单数据。
ID,FIRST_NAME,LAST_NAME,PAYDATE,AMT
912367,Jim,Smith,1/1/2000,5000
1102467,LAURA,JAMES,1/1/2000,5000
812367,DAVID,johnson,1/1/2000,5000
555555,ian,Smith,1/1/2000,5000
912367,Jim,SMITH,1/8/2000,4000
...
是的,这些名字很脏。说未命名的老板出现并说,用这个和其他数据做一些事情......然后给你一个名单。当然,他们的格式正确:
Smith,Jim R
Fields,Samantha
Smith,Kelly
Lensdotter,Patricia
我选择打破它们(在csv中很容易)以类似于
的方式阅读它们fnames <- c(Jim,Samantha,Kelly,Patricia)
和相关的姓氏(即2个变量)。然后我在数据框中读取,做了一些嵌套循环和greps(忽略大小写)。搜索了更简单的方法,并找到了如何&#34; python zip&#34;列表等,但我想知道是否有更简单的方法?
我的代码非常类似于:
EID <- vector(mode="integer")
for (i in 1:length(lnames)){
l <- lnames[i]
f <- fnames[i]
if(grepl(l,payroll[3],ignore.case = T)){
paycut1 <- payroll[grepl(l,payroll$LAST_NAME,ignore.case = T),]
if(grepl(f,paycut[2],ignore.case=T)){
paycut2 <- paycut[grepl(f,paycut$FIRST_NAME,ignore.case=T),]
}
print(paste0(l,", ",f," Has EID: ", paycut2[1,1]))
EIDs <- c(EIDs,paycut2[1,1])
}else{
print(paste0(l,", ",f," NOT in Payroll Data: "))
}
}
因此我可以从与名称相关联的文件中获取ID(因此我不必处理名称!)。有什么建议? (我不想使用for (i in range):
构造(一种不优雅的构造)而不是像for i,j:
构造那样的更多c / python。
(对不起开头的解释,但我认为搜索这样的问题值得回答,并不是每个人都可以正确构建一个问题,所以答案就像&#34;只是向量化它&#34;这可能是在他们的情况下不适用于阻止他们继续询问)
P.S。如果我以完全错误的方式解决这个问题,我并不反对其他观点。我来自C背景,因此我习惯于循环和非矢量化代码。我只是无法看到如何对此进行矢量化。批评,虽然只是有用的批评,但欢迎。
答案 0 :(得分:1)
只是矢量化它!
更严重的是,您的代码看起来并不像R代码 - 如果您可以帮助它,您真的不想嵌套循环。
以下是我将如何做到这一点。
首先我们清理名称:
payroll$FIRST_NAME <- toupper(payroll$FIRST_NAME)
payroll$LAST_NAME <- toupper(payroll$LAST_NAME)
names$V2 <- toupper(sub(" .*", "", names$V2))
names$V1 <- toupper(names$V1)
然后我们可以使用inner_join来匹配那些:
library(dplyr)
inner_join(names, payroll, by = c(V2 = "FIRST_NAME", V1 = "LAST_NAME"))
V1 V2 ID PAYDATE AMT
1 SMITH JIM 912367 1/1/2000 5000
2 SMITH JIM 912367 1/8/2000 4000
那些不匹配的,使用anti_join:
anti_join(names, payroll, by = c(V2 = "FIRST_NAME", V1 = "LAST_NAME"))
V1 V2
1 SMITH KELLY
2 LENSDOTTER PATRICIA
3 FIELDS SAMANTHA
以下是我获取数据的方式:
payroll <- read.table(text = "ID,FIRST_NAME,LAST_NAME,PAYDATE,AMT
912367,Jim,Smith,1/1/2000,5000
1102467,LAURA,JAMES,1/1/2000,5000
812367,DAVID,johnson,1/1/2000,5000
555555,ian,Smith,1/1/2000,5000
912367,Jim,SMITH,1/8/2000,4000", header=TRUE, sep = ",")
names <- read.table(text="Smith,Jim R
Fields,Samantha
Smith,Kelly
Lensdotter,Patricia", header=FALSE, sep = ",")