然后,逐行排序在数据框的特定列之间进行连接

时间:2015-02-25 21:40:20

标签: r sorting row string-concatenation mapply

(不包括排序的相关question。当您不需要排序时,可以轻松使用paste。)

我有一个不太理想的结构表,其中的字符列是通用的" item1"," item2"我想创建一个新的字符变量,它是这些列的按字母顺序排列的逗号分隔串联。例如,在第5行中,如果item1 =" milk",item2 =" eggs"和item3 =" butter",第5行中的新变量可能是"黄油,鸡蛋,牛奶"

我在下面编写了一个函数f(),它可以处理两个字符变量。但是,我遇到了麻烦

  • 使用mapply或其他"矢量化" (我知道它真的只是一个for循环)
  • 将函数概括为任意数量的列

任何帮助非常感谢。

df <- data.frame(a =c("foo","bar"), 
                 b= c("baz","qux"))   
paste(df$a,df$b, sep=", ")
# returns [1] "foo, baz" "bar, qux" ... but I want [1] "baz, foo" "bar, qux"

f <- function(a,b) paste(c(a,b)[order(c(a,b))],collapse=", ")
f("foo","baz") 
# returns [1] "baz, foo" ... which is what I want ... how to vectorize?

df$new_var <- mapply(f, df$a, df$b)
df 
#     a   b new_var      <- new_var is not what I want
# 1 foo baz    1, 2
# 2 bar qux    1, 2

# Interestingly, data.table is smart enough to fix my bad mapply
library(data.table)
dt <- data.table(a =c("foo","bar"), 
                 b= c("baz","qux"))  
dt[,new_var:=mapply(f, a, b)]
dt
#     a    b  new_var    <- new var IS what I want
# 1: foo baz baz, foo
# 2: bar qux bar, qux

2 个答案:

答案 0 :(得分:3)

我的第一个想法是做到这一点:

dt[, new_var := paste(sort(.SD), collapse = ", "), by = 1:nrow(dt)]

但是你可以通过几个简单的修改来使你的功能工作:

f = function(...) paste(c(...)[order(c(...))],collapse=", ")

dt[, new_var := do.call(function(...) mapply(f, ...), .SD)]

答案 1 :(得分:3)

只需按下行:

apply(df,1,function(x){
  paste(sort(x),collapse = ",")
})

如果你愿意,可以将它包裹在一个函数中。您必须定义要发送或假设所有列的列。即申请(df [,2:3],1,f()...

sort(x)与x [order(x)]

相同
相关问题