【问题标题】:Overwrite levels of factor columns in one dataframe using another使用另一个数据帧覆盖一个数据帧中因子列的级别
【发布时间】:2019-07-08 22:49:38
【问题描述】:

我有 2 个包含多个因子列的数据框。一个是基础数据帧,另一个是最终数据帧。我想使用最终数据框更新基础数据框的级别。

考虑这个例子:

base <- data.frame(product=c("Business Call", "Business Transactional", 
                             "Monthly Non-Compounding and Standard Non-Compounding",
                             "OCR based Call", "Offsale Call", "Offsale Savings",
                             "Offsale Transactional", "Out of Scope","Personal Call"))
base$product <- as.factor(base$product)

final <- data.frame(product=c("Business Call", "Business Transactional", 
                              "Monthly Standard Non-Compounding", "OCR based Call", 
                              "Offsale Call", "Offsale Savings","Offsale Transactional", 
                              "Out of Scope","Personal Call", "You Money")) 
final$product <- as.factor(final$product)

我现在想要的是最终数据库具有与基础相同的级别,并删除根本不存在的级别,例如“You Money”。而“月标准非复合”要模糊匹配

例如:

levels(base$var1) <- "a" "b" "c"
levels(final$var1) <- "Aa" "Bb" "Cc"

有没有办法通过某种模糊匹配使用最终数据覆盖基础数据中的级别?

就像我希望两个数据的最终级别相同。即

levels(base$var1) <- "Aa" "Bb" "Cc"
levels(final$var1) <- "Aa" "Bb" "Cc"

【问题讨论】:

  • 模糊匹配是什么意思?
  • 如果标签的顺序保持在两个数据帧之间,也许我们可以简单地base$var1 = factor(base$var1, levels(base$var1), levels(final$var1))
  • 我添加了一个工作示例! @OmG
  • @Quar 我添加了一个工作示例

标签: r factors levels


【解决方案1】:

我们可以建立自己的fuzzyMatcher

首先,我们需要一个矢量化的agrep 函数,

agrepv <- function(x, y) all(as.logical(sapply(x, agrep, y)))

我们在其上构建fuzzyMatcher

fuzzyMatcher <-  function(from, to) { 
  mc <- mapply(function(y) 
    which(mapply(function(x) agrepv(y, x), Map(levels, to))), 
    Map(levels, from))
  return(Map(function(x, y) `levels<-`(x, y), base, 
             Map(levels, from)[mc]))
}

final 标签应用于base 标签(注意,我已经移动了列以使其更复杂一些):

base[] <- fuzzyMatcher(final1, base1)
#    X1 X2
# 1  Aa Xx
# 2  Aa Xx
# 3  Aa Yy
# 4  Aa Yy
# 5  Bb Yy
# 6  Bb Zz
# 7  Bb Zz
# 8  Aa Xx
# 9  Cc Xx
# 10 Cc Zz

更新

根据上面提供的新数据,使用另一个矢量化agrepv2() 是有意义的,它与outer() 一起使用,使我们能够将agrep 应用于两个向量级别的所有组合。此后colSums 等于零给我们非匹配级别和which.max 目标数据帧final 的匹配级别。我们可以使用这两个结果向量,一方面删除未使用的final 行,另一方面对base 数据框的所需级别进行子集化,以重建因子列。

# add to mimic other columns in data frame
base$x <- seq(nrow(base))
final$x <- seq(nrow(final))

# some abbrevations for convenience
p1 <- levels(base$product)
p2 <- levels(final$product)

# agrep
AGREPV2 <- Vectorize(function(x, y, ...) agrep(p2[x], p1[y]))  # new vectorized agrep 
out <- t(outer(seq(p2), seq(p1), agrepv2, max.distance=0.9))  # apply `agrepv2`
del.col <- grep(0, colSums(apply(out, 2, lengths))) # find negative matches
lvl <- unlist(apply(out, 2, which.max))  # find positive matches
lvl <- as.character(p2[lvl])  # get the labels

# delete "non-existing" rows and re-generate factor with new labels
transform(final[-del.col, ], product=factor(product, labels=lvl))
#                  product x
# 1          Business Call 1
# 2 Business Transactional 2
# 4         OCR based Call 4
# 5           Offsale Call 5
# 6        Offsale Savings 6
# 7  Offsale Transactional 7
# 8           Out of Scope 8
# 9          Personal Call 9

数据

base1 <- structure(list(X1 = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 
3L, 3L), .Label = c("a", "b", "c"), class = "factor"), X2 = structure(c(1L, 
1L, 2L, 2L, 2L, 3L, 3L, 1L, 1L, 3L), .Label = c("x", "y", "z"
), class = "factor")), row.names = c(NA, -10L), class = "data.frame")

final1 <- structure(list(X1 = structure(c(1L, 3L, 1L, 1L, 2L, 3L, 2L, 1L, 
2L, 2L, 3L, 3L, 2L, 2L, 2L), .Label = c("Xx", "Yy", "Zz"), class = "factor"), 
    X2 = structure(c(2L, 1L, 1L, 2L, 2L, 3L, 3L, 1L, 1L, 2L, 
    2L, 2L, 2L, 2L, 3L), .Label = c("Aa", "Bb", "Cc"), class = "factor")), row.names = c(NA, 
-15L), class = "data.frame")

【讨论】:

  • 顺序不同时不起作用。你觉得有办法吗?此外,当级别不相等时
  • @BruceWayne 如果你能设计一个独立的minimal reproducible example,那就太好了。
  • 当然!让我试试
  • 我已经更新了一个新示例,这正是我想要复制的内容
  • @BruceWayne 太好了,请参阅更新。我不知道你想对“不存在的关卡”做什么,因为它们确实存在。我决定删除这些行。另一种方法是将它们设置为NA 或将它们命名为"unmatched"?
猜你喜欢
  • 2018-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
  • 2016-07-24
  • 2016-09-15
相关资源
最近更新 更多