我是R的新手所以请耐心等待。我有两个数据帧dfA和dfB。
dfA
Type
Test1 11000
11000 Test2
Test3 11000
11000 Test4
Test5 11001
Test6 11002
Test7 11003
Test8 11004
Test9 11004
Test10 11006
DFB
Asset NO No
11000 1
11001 2
11002 3
11003 4
11004 5
11005 6
11006 7
11007 8
11008 9
11009 10
Desired Out Put
Type No
Test1 11000 1
11000 Test2 1
Test3 11000 1
11000 Test4 1
Test5 11001 2
Test6 11002 3
Test7 11003 4
Test8 11004 5
Test9 11004 5
Test10 11006 7
我相信forloop和grepl是必需的。如果有人可以帮助我如何记下forloop会有很大的帮助。
答案 0 :(得分:1)
如果dfB$No
只是一个行号,我只会做
match(as.integer(sub(".*(\\b\\d+\\b).*", "\\1", dfA$Type)), dfB$AssetNO)
## [1] 1 1 1 1 2 3 4 5 5 7
这将仅捕获dfA$Type
中的整数(以单词绑定为界),然后匹配回dfB$AssetNO
否则,只需稍加修改即可
indx <- match(as.integer(sub(".*(\\b\\d+\\b).*", "\\1", dfA$Type)), dfB$AssetNO)
dfB[indx, "No"]
## [1] 1 1 1 1 2 3 4 5 5 7
作为旁注,您的数据似乎搞砸了。您可能应该尝试以一致的格式记录数据。通过这种方式,可以避免使用正则表达式,从而大大提高性能。
答案 1 :(得分:0)
希望这有帮助
Type <- c("Test1 11000","11000 Test2","Test3 11000","11000 Test4","Test5 11001",
"Test6 11002","Test7 11003","Test8 11004","Test9 11004","Test10 11006")
Asset_NO <- seq(11000,11009,1)
No <- seq(1,10,1)
dfA <- data.frame(Type)
dfB <- data.frame(Asset_NO,No)
split <- str_split(dfA$Type, " ")
v <- c(NULL)
for (i in 1:length(split)) {
f <- sapply(split, "[",1)
s <- sapply(split, "[",2)
#v <- ifelse(grepl("Test",f), s, f)
v <- ifelse(grepl("[a-zA-Z]",f), s, f) #As per the new cooment
}
dfA$Asset_NO <- v
dfA$Asset_NO <- as.numeric(dfA$Asset_NO)
m <- merge(dfA, dfB, by="Asset_NO")
m
输出
Asset_NO Type No
1 11000 Test1 11000 1
2 11000 11000 Test2 1
3 11000 Test3 11000 1
4 11000 11000 Test4 1
5 11001 Test5 11001 2
6 11002 Test6 11002 3
7 11003 Test7 11003 4
8 11004 Test8 11004 5
9 11004 Test9 11004 5
10 11006 Test10 11006 7
答案 2 :(得分:0)
我首先为名为dfA
的{{1}}创建一个新列:
并使用NEW
将所有字母替换为空字符串gsub
。这给了我一个两个数字的向量,但我通过对数字进行排序来寻找有意义的数字,一个是索引,另一个是根据""
中Asset_NO
的列的值/ p>
dfB
我确保这些都是数字形式,所以比较苹果和橘子。
dfA$NEW = NA
for(i in 1:nrow(dfA)){
temp = as.numeric(strsplit(gsub("[[:alpha:]]", "", dfA$Type[i]), split = " ")[[1]])
dfA$NEW[i] = (sort(temp, decreasing = T)[1])
}
然后我需要做的就是合并它们。
dfB$Asset_NO = as.numeric(dfB$Asset_NO)
答案 3 :(得分:0)
您可以使用Asset_NO
和简单的dfB
语句以及gregexpr
在ifelse
中创建列merge
,如下所示,
dfA$Asset_NO <- ifelse(sapply(gregexpr('[A-Za-z]+', dfA$Type), '[', 1) > 1,
gsub('\\s+.*', '', dfA$Type), gsub('.*\\s+', '', dfA$Type))
merge(dfA, dfB)
# Asset_NO Type No
#1 11000 Test1 11000 1
#2 11000 11000 Test2 1
#3 11000 Test3 11000 1
#4 11000 11000 Test4 1
#5 11001 Test5 11001 2
#6 11002 Test6 11002 3
#7 11003 Test7 11003 4
#8 11004 Test8 11004 5
#9 11004 Test9 11004 5
#10 11006 Test10 11006 7
答案 4 :(得分:0)
这是使用data.table
和stringr
的另一种方法:
library(data.table)
dfA[, Asset := as.integer(stringr::str_extract(Type, "(^\\d{5})|(\\d{5}$)"))]
dfB[dfA, on = "Asset", .(Type, No)]
# Type No
# 1: Test1 11000 1
# 2: 11000 Test2 1
# 3: Test3 11000 1
# 4: 11000 Test4 1
# 5: Test5 11001 2
# 6: Test6 11002 3
# 7: Test7 11003 4
# 8: Test8 11004 5
# 9: Test9 11004 5
#10: Test10 11006 7
#11: Test111000 1
#12: 11000Test2 1
#13: Test311000 1
#14: 11000Test4 1
#15: Test511001 2
#16: Test611002 3
#17: Test711003 4
#18: Test811004 5
#19: Test911004 5
#20: Test1011006 7
请注意,所有答案在用于从Type
中提取资产编号的正则表达式上有所不同。这是由于原始问题中提供的规格较差。
此处使用的正则表达式假设资产编号始终由五位数组成,Type
以资产编号开头或结尾。这与任何单词边界无关,因此也适用于Type
中不包含空格的情况。
将提取的资产编号分配到新列dfA
后,dfB
上的Asset
加入。
我刚刚意识到OP在各种评论中都披露了重要信息:
@etienne这是一行没有列所以理想情况下一个单词'11000Test2''Test311000'因此使用grepl和搜索第二个df的原因是因为数字不符合需要使用搜索来匹配,否则可能删除了缩写并进行了匹配。
和
不能将grepl用作“test”,因为所有Type都没有被提及为Test这只是真实数据中的一个例子。因此基本上需要用数字进行搜索,所以从dfB搜索第一个数字并将其与dfA匹配,然后从dfB的b列获得输出,如果没有匹配则从第2个df中选择第2个数字,依此类推......
但是,只要OP不能提供更实际的生产数据样本,只要资产数量可以通过正则表达式从Type
无法提取,就无需查询如果Type
中存在匹配项,则为每个给定的资产编号。