如何防止合并重新排序列

Posted

技术标签:

【中文标题】如何防止合并重新排序列【英文标题】:How to prevent merge from reordering columns 【发布时间】:2013-07-08 15:11:46 【问题描述】:

在下面的例子中

x <- data.frame(code = 7:9, food = c('banana', 'apple', 'popcorn'))
y <- data.frame(food = c('banana', 'apple', 'popcorn'),
                isfruit = c('fruit', 'fruit', 'not fruit'))

我想做x &lt;- merge(x, y),但问题是merge() 重新排序列,以便by 列(食物)排在第一位。 我怎样才能防止这种情况并让merge(x, y) 使用 x 的相同列顺序,只需将新变量 (isFruit) 作为第三列插入(即“code, food, isFruit”而不是“food, code,是水果”)?

我试过了,没用:

merge(x, y, sort = F)

我的解决方法是以后再做

x <- x[c(2, 1, 3)]

【问题讨论】:

我认为您的解决方法就是解决方案。 ...虽然 plyr 包中的 join 似乎没有重新排序列。 【参考方案1】:

您可以将其包装在您的自定义函数中。例如:

merge.keep <- function(...,ord=union(names(x), names(y)))merge(...)[ord]

那么例如:

merge.keep(x,y)
  code    food   isfruit
1    8   apple     fruit
2    7  banana     fruit
3    9 popcorn not fruit

EDIT 我使用@Eddi idea 来设置 ord 的默认值。

【讨论】:

-1 因为这不会向 OP 添加任何内容 - OP 想要的是 不必 必须手动指定订单 @eddi 很好,即使我不同意反对票(我觉得有点尖锐)。我的想法是创建一个扩展合并函数的函数。我使用您的好主意编辑我的答案以设置订单的默认值。 @agstudy 你好,如果我有不同名称的数据表(例如 x = DT1,y = DT2)并且我在这些数据表的不同列上合并,则此解决方案不起作用。错误消息:as.vector(x) 中的错误:找不到对象“x”。有道理,因为数据表一开始没有命名为 x 和 y。我试图找到一种解决方法,但没有成功。您知道如何调整解决方案,使其更适用于(更复杂的)数据表合并吗?【参考方案2】:

plyr 让这一切变得简单:

 x <- data.frame(code = 7:9, food = c('banana', 'apple', 'popcorn'))
 y <- data.frame(food = c('banana', 'apple', 'popcorn'),
                isfruit = c('fruit', 'fruit', 'not fruit'))

library(plyr)
join(x,y)

        #GOOD 
#Joining by: food
#  code    food   isfruit
#1    7  banana     fruit
#2    8   apple     fruit
#3    9 popcorn not fruit

    #BAD  
# merge(x,y)
#     food code   isfruit
#1   apple    8     fruit
#2  banana    7     fruit
#3 popcorn    9 not fruit

【讨论】:

plyr 一下子解决了我的一堆问题。感谢您的提示!【参考方案3】:

这是您的基本解决方法的通用版本:

merge(x, y)[, union(names(x), names(y))]

【讨论】:

请注意,为 col 名称传入 union 仅适用于数据帧,而不适用于数据表。 @Serenthia 添加, with = FALSEdata.table 使用“by.x=”和“by.y=”以及名称不同的列合并时失败。上述解决方法的一个丑陋版本是(使用 OP 修改的示例数据,将“food”和“food2”作为合并列):x &lt;- data.frame(code = 7:9, food = c('banana', 'apple', 'popcorn')) ; y &lt;- data.frame(food2 = c('banana', 'apple', 'popcorn'), isfruit = c('fruit', 'fruit', 'not fruit')) ; byY="food2" ; merge(x, y, by.x="food",by.y=byY)[, union(names(x), subset(names(y), names(y)!=byY))]【参考方案4】:

如果您只引入一列并想最后附加它,那么merge 可能是多余的,您可以使用match-[indexing 方法进行评估:

> x$isfruit <- y$isfruit[match(y$food, x$food)]
> x
  code    food   isfruit
1    7  banana     fruit
2    8   apple     fruit
3    9 popcorn not fruit

(在合并功能中没有任何开关可以满足您的要求。)

【讨论】:

感谢您的输入,但我的真实数据涉及两个数十列的数据框。

以上是关于如何防止合并重新排序列的主要内容,如果未能解决你的问题,请参考以下文章

UNION表时如何在Bigquery中重新排列/重新排序嵌套的重复列

合并数据框重新排序列

数据表 - 如何防止排序列改变颜色

如何防止重新排序 UICollectionView 中的最后一个单元格?

如何防止 Mongoose 在修改用户后重新散列用户密码?

熊猫如何交换或重新排序列