2013-02-24 85 views
-1

我想合并两个数据框后合并列。现在,我正在编写ifelse语句来为每个变量获取一个统一的列。我想要一个函数来选择什么数据帧(即x)应该覆盖另一列。在R中合并后合并列的函数

df$source<-ifelse(df$source.x=='',df$source.y,df$source.x) 
df$id<-ifelse(df$id.x=='',df$id.y,df$id.x) 
df$profile_url<-ifelse(df$profile_url.x=='',df$profile_url.y,df$profile_url.x) 

任何帮助,将不胜感激

+0

这只是有点不清楚......对于上面的列,你想让df带上y的值iff x是一个空字符串,否则从x取值? – 2013-02-24 06:26:07

+1

你如何做你的合并?你能给出上下文吗?并请提供一个可重复的例子。 – agstudy 2013-02-24 06:26:10

回答

3

这样应该可以做到这一点。 (注意,没有经过测试,因为没有样本数据)

fixedColumn <- function(colm, myDF, keepx=TRUE) { 
    x <- myDF[[paste0(colm, ".x")]] 
    y <- myDF[[paste0(colm, ".y")]] 

    if(keepx) 
    return(ifelse(x=='', y, x)) 
    # else 
    ifelse(y=='', x, y) 
} 

# columns that need fixing. Don't include the suffixes 
cols <- c("source", "id", "url") 

# fix the .x columns 
df[, paste0(cols, ".x")] <- sapply(cols, fixedColumn, df) 

# delete the .y columns 
for (cc in paste0(cols, ".y")) 
    df[[cc]] <- NULL 

使用@ agstudy的样本数据:

> df 
    Row.names id.x source.x url.x 
1   1 2  2  3 
2   2 3  1  3 
3   3 3  1  2 
4   4 3  2  2 
5   5 3  2  2 
+0

+1;可能稍微快一点就可以做到这一点:'x < - myDF [[paste0(colm,“.x”)]]; x [x ==''] < - myDF [[paste0(colm,“.y”)]] [x =='']' – 2013-02-24 06:35:45

+0

但这里这段代码不起作用我想!你的宝瓶中缺少“colm”,不是吗? – agstudy 2013-02-24 06:42:23

+0

@agstudy,赶上,谢谢!我修复了'sapply'语句和函数定义匹配。 – 2013-02-24 06:55:21

2

为了避免交换柱的这一步,你可以通过sqldf包中使用SQL交换列(如果你真正的问题涉及到可以同时完成的合并)。使用CASE ... WHEN语法你写相同的if/else逻辑,我们有:

library(sqldf) 
colnames(df) <- gsub('[.]','_',colnames(df)) 
sqldf(" SELECT 
      CASE url_x WHEN '' THEN url_y ELSE url_x END as url , 
      CASE source_x WHEN '' THEN source_y ELSE source_x END as source, 
      CASE id_x WHEN '' THEN id_y ELSE id_x END as id 
     FROM df") 

重复的例子,

我们有一个重复的例子测试:

# create some data 
set.seed(1234) 
df1 <- matrix(sample(c('a','b','d',''),3*5,rep=T),ncol=3) 
df2 <- matrix(sample(c('c','b','','a'),3*5,rep=T),ncol=3) 
colnames(df1) <- c('id','source','url') 
colnames(df2) <- c('id','source','url') 
df <- merge(df1,df2,by=0) 

# run 
library(sqldf) 
colnames(df) <- gsub('[.]','_',colnames(df)) 
sqldf(" SELECT 
      CASE url_x WHEN '' THEN url_y ELSE url_x END as url , 
      CASE source_x WHEN '' THEN source_y ELSE source_x END as source, 
      CASE id_x WHEN '' THEN id_y ELSE id_x END as id 
     FROM df") 

url source id 
1 d  d a 
2 d  a d 
3 b  a d 
4 a  d d 
5 b  d c 

其中df是:

Row_names id_x source_x url_x id_y source_y url_y 
1   1 a  d  d a  b  a 
2   2 d  a  d b  b  
3   3 d  a  b b  c  a 
4   4 d  d   c  c  a 
5   5    d  b c  c  c 

使用辅助函数

(1)如果我们有很多的这些那么我们可能需要使用一个辅助功能,这使得使用fn$从实现准的Perl风格的字符串替换的gsubfn包:

xy <- function(s) { 
    fn$identity("case $s_x when '' then $s_y else $s_x end as $s") 
} 

fn$sqldf("select `xy('url')`, `xy('source')`, `xy('id')` from df") 

(2)或做这种方式 - 存储SQL语句为s

s <- fn$identity("select `xy('url')`, `xy('source')`, `xy('id')` from df") 
sqldf(s) 

更多信息

sqldf home pagefn$看到gsubfn home page