根据两列的 matching/fuzzy 匹配值选择列
Selecting columns based on matching/fuzzy matching value of two columns
我有包含列 "Year"
和 "Agent"
的数据框 df1
:
df1 <- structure(list(Year = c(1999, 1999, 1998), Agent = list(c("abn-amro-nv", "suntrust banks", "wachovia"), c("jp morgan", "abn-amro-nv"), c("ba-corp", "boston bks", "nbd"))), .Names = c("Year", "Agent"), row.names = c(NA, -3L), class = "data.frame")
#df1
Year Agent
1999 abn-amro-nv, suntrust banks, wachovia
1999 jp morgan, abn-amro-nv
1998 ba-corp, boston bks, nbd
我有另一个数据框 df2
,它有 5 列 "Rank"
、"Arrangers"
、"Share"
、"Issues"
和 "Year"
,如以下:
df2 <- structure(list(Rank = 1:3, Arranger = c("jp morgan", "boston-bank", "suntrust bk"), Share = c(1.2, 1.8, 2.1), Issues = c(7L, 4L, 3L), Year = c(1999L, 1998L, 1999L)), .Names = c("Rank", "Arranger", "Share", "Issues", "Year"), class = "data.frame", row.names = c(NA, -3L))
#df2
Rank Arranger Share Issues Year
1 jp morgan 1.2 7 1999
2 boston-bank 1.8 4 1998
3 suntrust bk 2.1 3 1999
我需要将 df1
的 "Agent"
和 "Year"
与 df2
和 select 的 "Arranger"
和 "Year"
匹配df2
中的 3 列,例如 "Rank"
、"Share"
、"Issues"
。
df1
的"Agent"
与df2
的"Arranger"
的匹配为模糊匹配。这是因为它们并不完全相同。
我的原始数据框很大,仅供参考。
以下是我的代码:
library(stringdist)
leadrep <- matrix(ncol=3, nrow=length(df1$Agent))
for (i in 1:length(df1$Agent)) {
for (j in 1:length(df2$Arrangers)) {
if ((ain(df2$Arrangers[j], df1$Agent[[i]], maxDist=0.3,
method="jw")) == 'TRUE' & (df1$Year[i] == df2$Year[j])){
leadrep[i,] <- df2[j, c('Rank', 'Mkt.Share', 'NumberofIssues')]
}
}
}
在代码中,leadrep
是我创建的矩阵。这样我就可以填充 for loop
。我使用 stringdist
包和 ain
函数来进行模糊匹配。我用两个 for loop
和 if
来比较字符串和年份。
上面的代码可以工作,但是由于我的数据帧很大,所以需要很长时间才能得到结果。我真的认为我上面的方法效率不高。如果有人为我提供一个更好的替代现有代码的方法,那将是一个很大的帮助。
感谢您的帮助。
以下方法使用 foreach
而不是两个嵌套的 for
循环,这将使您在大型数据帧上的计算速度更快。请参阅 this 了解该软件包的概览。你还应该看看小插曲。
library(foreach)
library(stringdist)
match.cond <- function(ij, df1, df2) { ## 1.
i = floor((ij-1) / nrow(df2)) + 1
j = ij - (i-1) * nrow(df2)
if ((ain(df2$Arranger[j], df1$Agent[[i]], maxDist=0.3,
method="jw")) == 'TRUE' & (df1$Year[i] == df2$Year[j])){
return(df2[j, c('Rank', 'Share', 'Issues')])
}
}
leadrep <- foreach(ij = 1:(nrow(df1)*nrow(df2)), .combine=rbind) %do% ## 2.
match.cond(ij, df1, df2)
备注:
match.cond
是你的匹配条件封装到一个 kernel 函数中,它将被 foreach
vectorized来自 df1
和 df2
的所有行对。它的输入是 ij
,这是配对的索引,以及两个数据帧。 match.cond
以内:
ij
转换为 df1
的行索引 i
和 df2
的 j
- 你的条件被评估,如果满足条件,
- 返回
df2
中匹配行的列。
- 这是
foreach
通话。
- 我们遍历从
1
到 nrow(df1)*nrow(df2)
的索引 ij
,它枚举了来自 df1
和 df2
和 [=33] 的所有行对=] match.cond
函数。请注意,这都是一行。
.combine=rbind
参数声明我们要从 match.cond
收集所有结果并将它们绑定为行。
- 这个returns数据框
leadrep
我已经对你的数据进行了测试,dput
:
df1 <- structure(list(Year = c(1999, 1999, 1998), Agent = list(c("abn-amro-nv",
"suntrust banks", "wachovia"), c("jp morgan", "abn-amro-nv"),
c("ba-corp", "boston bks", "nbd"))), .Names = c("Year", "Agent"
), row.names = c(NA, -3L), class = "data.frame")
df2 <- structure(list(Rank = 1:3, Arranger = c("jp morgan", "boston-bank",
"suntrust bk"), Share = c(1.2, 1.8, 2.1), Issues = c(7L, 4L,
3L), Year = c(1999L, 1998L, 1999L)), .Names = c("Rank", "Arranger",
"Share", "Issues", "Year"), class = "data.frame", row.names = c(NA,
-3L))
这给了我想要的结果:
print(leadrep)
## Rank Share Issues
##3 3 2.1 3
##2 1 1.2 7
##21 2 1.8 4
希望这对您有所帮助。
我有包含列 "Year"
和 "Agent"
的数据框 df1
:
df1 <- structure(list(Year = c(1999, 1999, 1998), Agent = list(c("abn-amro-nv", "suntrust banks", "wachovia"), c("jp morgan", "abn-amro-nv"), c("ba-corp", "boston bks", "nbd"))), .Names = c("Year", "Agent"), row.names = c(NA, -3L), class = "data.frame")
#df1
Year Agent
1999 abn-amro-nv, suntrust banks, wachovia
1999 jp morgan, abn-amro-nv
1998 ba-corp, boston bks, nbd
我有另一个数据框 df2
,它有 5 列 "Rank"
、"Arrangers"
、"Share"
、"Issues"
和 "Year"
,如以下:
df2 <- structure(list(Rank = 1:3, Arranger = c("jp morgan", "boston-bank", "suntrust bk"), Share = c(1.2, 1.8, 2.1), Issues = c(7L, 4L, 3L), Year = c(1999L, 1998L, 1999L)), .Names = c("Rank", "Arranger", "Share", "Issues", "Year"), class = "data.frame", row.names = c(NA, -3L))
#df2
Rank Arranger Share Issues Year
1 jp morgan 1.2 7 1999
2 boston-bank 1.8 4 1998
3 suntrust bk 2.1 3 1999
我需要将 df1
的 "Agent"
和 "Year"
与 df2
和 select 的 "Arranger"
和 "Year"
匹配df2
中的 3 列,例如 "Rank"
、"Share"
、"Issues"
。
df1
的"Agent"
与df2
的"Arranger"
的匹配为模糊匹配。这是因为它们并不完全相同。
我的原始数据框很大,仅供参考。
以下是我的代码:
library(stringdist)
leadrep <- matrix(ncol=3, nrow=length(df1$Agent))
for (i in 1:length(df1$Agent)) {
for (j in 1:length(df2$Arrangers)) {
if ((ain(df2$Arrangers[j], df1$Agent[[i]], maxDist=0.3,
method="jw")) == 'TRUE' & (df1$Year[i] == df2$Year[j])){
leadrep[i,] <- df2[j, c('Rank', 'Mkt.Share', 'NumberofIssues')]
}
}
}
在代码中,leadrep
是我创建的矩阵。这样我就可以填充 for loop
。我使用 stringdist
包和 ain
函数来进行模糊匹配。我用两个 for loop
和 if
来比较字符串和年份。
上面的代码可以工作,但是由于我的数据帧很大,所以需要很长时间才能得到结果。我真的认为我上面的方法效率不高。如果有人为我提供一个更好的替代现有代码的方法,那将是一个很大的帮助。
感谢您的帮助。
以下方法使用 foreach
而不是两个嵌套的 for
循环,这将使您在大型数据帧上的计算速度更快。请参阅 this 了解该软件包的概览。你还应该看看小插曲。
library(foreach)
library(stringdist)
match.cond <- function(ij, df1, df2) { ## 1.
i = floor((ij-1) / nrow(df2)) + 1
j = ij - (i-1) * nrow(df2)
if ((ain(df2$Arranger[j], df1$Agent[[i]], maxDist=0.3,
method="jw")) == 'TRUE' & (df1$Year[i] == df2$Year[j])){
return(df2[j, c('Rank', 'Share', 'Issues')])
}
}
leadrep <- foreach(ij = 1:(nrow(df1)*nrow(df2)), .combine=rbind) %do% ## 2.
match.cond(ij, df1, df2)
备注:
match.cond
是你的匹配条件封装到一个 kernel 函数中,它将被foreach
vectorized来自df1
和df2
的所有行对。它的输入是ij
,这是配对的索引,以及两个数据帧。match.cond
以内:ij
转换为df1
的行索引i
和df2
的 - 你的条件被评估,如果满足条件,
- 返回
df2
中匹配行的列。
j
- 这是
foreach
通话。- 我们遍历从
1
到nrow(df1)*nrow(df2)
的索引ij
,它枚举了来自df1
和df2
和 [=33] 的所有行对=]match.cond
函数。请注意,这都是一行。 .combine=rbind
参数声明我们要从match.cond
收集所有结果并将它们绑定为行。- 这个returns数据框
leadrep
- 我们遍历从
我已经对你的数据进行了测试,dput
:
df1 <- structure(list(Year = c(1999, 1999, 1998), Agent = list(c("abn-amro-nv",
"suntrust banks", "wachovia"), c("jp morgan", "abn-amro-nv"),
c("ba-corp", "boston bks", "nbd"))), .Names = c("Year", "Agent"
), row.names = c(NA, -3L), class = "data.frame")
df2 <- structure(list(Rank = 1:3, Arranger = c("jp morgan", "boston-bank",
"suntrust bk"), Share = c(1.2, 1.8, 2.1), Issues = c(7L, 4L,
3L), Year = c(1999L, 1998L, 1999L)), .Names = c("Rank", "Arranger",
"Share", "Issues", "Year"), class = "data.frame", row.names = c(NA,
-3L))
这给了我想要的结果:
print(leadrep)
## Rank Share Issues
##3 3 2.1 3
##2 1 1.2 7
##21 2 1.8 4
希望这对您有所帮助。