Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 将多列粘贴在一起_R_Paste_R Faq_Purrr - Fatal编程技术网

R 将多列粘贴在一起

R 将多列粘贴在一起,r,paste,r-faq,purrr,R,Paste,R Faq,Purrr,我在一个数据框中有一组列,我想将它们粘贴在一起(以“-”分隔),如下所示: data <- data.frame('a' = 1:3, 'b' = c('a','b','c'), 'c' = c('d', 'e', 'f'), 'd' = c('g', 'h', 'i')) i.e. a b c d 1 a d g

我在一个数据框中有一组列,我想将它们粘贴在一起(以“-”分隔),如下所示:

data <- data.frame('a' = 1:3, 
                   'b' = c('a','b','c'), 
                   'c' = c('d', 'e', 'f'), 
                   'd' = c('g', 'h', 'i'))
i.e.     
     a   b   c  d  
     1   a   d   g  
     2   b   e   h  
     3   c   f   i  
do.call(sprintf, c(d[cols], '%s-%s-%s'))
我通常可以通过以下方式来实现:

within(data, x <- paste(b,c,d,sep='-'))
in(data,x
#您的起始数据.)。。
数据
#您的起始数据。。
数据<代码>库(plyr)
ldply(应用)数据,1,功能(x)数据帧(
x=粘贴(x[2:4],sep=“”,collapse=“-”))
#x
#1 a-d-g
#2b-e-h
#3c-f-i
#仅使用名称的矢量:
ldply(应用)数据,1,功能(x)数据帧(
x=粘贴(x[c('b','c','d')],sep=“”,collapse=“-”))
#或者同等地:
mynames
库(plyr)
ldply(应用)数据,1,功能(x)数据帧(
x=粘贴(x[2:4],sep=“”,collapse=“-”))
#x
#1 a-d-g
#2b-e-h
#3c-f-i
#仅使用名称的矢量:
ldply(应用)数据,1,功能(x)数据帧(
x=粘贴(x[c('b','c','d')],sep=“”,collapse=“-”))
#或者同等地:

mynames我将构建一个新的data.frame:

d <- data.frame('a' = 1:3, 'b' = c('a','b','c'), 'c' = c('d', 'e', 'f'), 'd' = c('g', 'h', 'i')) 

cols <- c( 'b' , 'c' , 'd' )

data.frame(a = d[, 'a'], x = do.call(paste, c(d[ , cols], list(sep = '-'))))

d我要构建一个新的data.frame:

d <- data.frame('a' = 1:3, 'b' = c('a','b','c'), 'c' = c('d', 'e', 'f'), 'd' = c('g', 'h', 'i')) 

cols <- c( 'b' , 'c' , 'd' )

data.frame(a = d[, 'a'], x = do.call(paste, c(d[ , cols], list(sep = '-'))))
d作为上的一个变量,定义了
数据
,并在
cols

cols <- c("b", "c", "d")

> data
  a     x
1 1 a-d-g
2 2 b-e-h
3 3 c-f-i
作为上的一个变体,使用已定义的
数据
,以及在
cols

cols <- c("b", "c", "d")

> data
  a     x
1 1 a-d-g
2 2 b-e-h
3 3 c-f-i

使用
tidyr
包,这可以在一个函数调用中轻松处理

data <- data.frame('a' = 1:3, 
                   'b' = c('a','b','c'), 
                   'c' = c('d', 'e', 'f'), 
                   'd' = c('g', 'h', 'i'))

tidyr::unite_(data, paste(colnames(data)[-1], collapse="_"), colnames(data)[-1])

  a b_c_d
1 1 a_d_g
2 2 b_e_h
3 3 c_f_i

使用
tidyr
包,这可以在一个函数调用中轻松处理

data <- data.frame('a' = 1:3, 
                   'b' = c('a','b','c'), 
                   'c' = c('d', 'e', 'f'), 
                   'd' = c('g', 'h', 'i'))

tidyr::unite_(data, paste(colnames(data)[-1], collapse="_"), colnames(data)[-1])

  a b_c_d
1 1 a_d_g
2 2 b_e_h
3 3 c_f_i

只需使用
Reduce
添加额外的解决方案,这可能比
do慢。call
但可能比
apply
要好,因为它将避免
矩阵的转换。此外,对于
循环,我们可以使用
setdiff
来删除不需要的列

cols <- c('b','c','d')
data$x <- Reduce(function(...) paste(..., sep = "-"), data[cols])
data[setdiff(names(data), cols)]
#   a     x
# 1 1 a-d-g
# 2 2 b-e-h
# 3 3 c-f-i
另一个选项是使用
.SDcols
而不是中的
mget

setDT(data)[, x := Reduce(function(...) paste(..., sep = "-"), .SD), .SDcols = cols]

只需使用
Reduce
添加额外的解决方案,这可能比
do慢。call
但可能比
apply
要好,因为它将避免
矩阵的转换。此外,对于
循环,我们可以使用
setdiff
来删除不需要的列

cols <- c('b','c','d')
data$x <- Reduce(function(...) paste(..., sep = "-"), data[cols])
data[setdiff(names(data), cols)]
#   a     x
# 1 1 a-d-g
# 2 2 b-e-h
# 3 3 c-f-i
另一个选项是使用
.SDcols
而不是中的
mget

setDT(data)[, x := Reduce(function(...) paste(..., sep = "-"), .SD), .SDcols = cols]

我对Anthony Damico、Brian Diggs和data_steve的答案在一个小样本
tbl_df
上进行了基准测试,得到了以下结果

> data <- data.frame('a' = 1:3, 
+                    'b' = c('a','b','c'), 
+                    'c' = c('d', 'e', 'f'), 
+                    'd' = c('g', 'h', 'i'))
> data <- tbl_df(data)
> cols <- c("b", "c", "d")
> microbenchmark(
+     do.call(paste, c(data[cols], sep="-")),
+     apply( data[ , cols ] , 1 , paste , collapse = "-" ),
+     tidyr::unite_(data, "x", cols, sep="-")$x,
+     times=1000
+ )
Unit: microseconds
                                         expr     min      lq      mean  median       uq       max neval
do.call(paste, c(data[cols], sep = "-"))       65.248  78.380  93.90888  86.177  99.3090   436.220  1000
apply(data[, cols], 1, paste, collapse = "-") 223.239 263.044 313.11977 289.514 338.5520   743.583  1000
tidyr::unite_(data, "x", cols, sep = "-")$x   376.716 448.120 556.65424 501.877 606.9315 11537.846  1000

我对Anthony Damico、Brian Diggs和data_steve的答案在一个小样本
tbl_df
上进行了基准测试,得到了以下结果

> data <- data.frame('a' = 1:3, 
+                    'b' = c('a','b','c'), 
+                    'c' = c('d', 'e', 'f'), 
+                    'd' = c('g', 'h', 'i'))
> data <- tbl_df(data)
> cols <- c("b", "c", "d")
> microbenchmark(
+     do.call(paste, c(data[cols], sep="-")),
+     apply( data[ , cols ] , 1 , paste , collapse = "-" ),
+     tidyr::unite_(data, "x", cols, sep="-")$x,
+     times=1000
+ )
Unit: microseconds
                                         expr     min      lq      mean  median       uq       max neval
do.call(paste, c(data[cols], sep = "-"))       65.248  78.380  93.90888  86.177  99.3090   436.220  1000
apply(data[, cols], 1, paste, collapse = "-") 223.239 263.044 313.11977 289.514 338.5520   743.583  1000
tidyr::unite_(data, "x", cols, sep = "-")$x   376.716 448.120 556.65424 501.877 606.9315 11537.846  1000

在我看来,
sprintf
-函数也应该在这些答案中占有一席之地。您可以如下使用
sprintf

data <- data.frame('a' = 1:3, 
                   'b' = c('a','b','c'), 
                   'c' = c('d', 'e', 'f'), 
                   'd' = c('g', 'h', 'i'))
i.e.     
     a   b   c  d  
     1   a   d   g  
     2   b   e   h  
     3   c   f   i  
do.call(sprintf, c(d[cols], '%s-%s-%s'))
其中:

 [1] "a-d-g" "b-e-h" "c-f-i"
并创建所需的数据帧:

data.frame(a = d$a, x = do.call(sprintf, c(d[cols], '%s-%s-%s')))
给予:

  a     x
1 1 a-d-g
2 2 b-e-h
3 3 c-f-i
尽管
sprintf
与@BrianDiggs的
do.call
/
paste
组合相比没有明显的优势,但当您还想填充所需字符串的某些部分或指定位数时,它尤其有用。有关几个选项,请参阅
?sprintf

另一种变体是从以下位置使用
pmap

注意:此
pmap
解决方案仅在列不是因子时有效


更大数据集上的基准:

# create a larger dataset
d2 <- d[sample(1:3,1e6,TRUE),]
# benchmark
library(microbenchmark)
microbenchmark(
  docp = do.call(paste, c(d2[cols], sep="-")),
  appl = apply( d2[, cols ] , 1 , paste , collapse = "-" ),
  tidr = tidyr::unite_(d2, "x", cols, sep="-")$x,
  docs = do.call(sprintf, c(d2[cols], '%s-%s-%s')),
  times=10)

使用数据:

d <- data.frame(a = 1:3, b = c('a','b','c'), c = c('d','e','f'), d = c('g','h','i')) 

d在我看来,
sprintf
-函数也应该在这些答案中占有一席之地。您可以使用
sprintf
,如下所示:

data <- data.frame('a' = 1:3, 
                   'b' = c('a','b','c'), 
                   'c' = c('d', 'e', 'f'), 
                   'd' = c('g', 'h', 'i'))
i.e.     
     a   b   c  d  
     1   a   d   g  
     2   b   e   h  
     3   c   f   i  
do.call(sprintf, c(d[cols], '%s-%s-%s'))
其中:

 [1] "a-d-g" "b-e-h" "c-f-i"
并创建所需的数据帧:

data.frame(a = d$a, x = do.call(sprintf, c(d[cols], '%s-%s-%s')))
给予:

  a     x
1 1 a-d-g
2 2 b-e-h
3 3 c-f-i
尽管
sprintf
与@BrianDiggs的
do.call
/
paste
组合相比没有明显的优势,但当您还想填充所需字符串的某些部分或指定位数时,它尤其有用。有关几个选项,请参阅
?sprintf

另一种变体是从以下位置使用
pmap

注意:此
pmap
解决方案仅在列不是因子时有效


更大数据集上的基准:

# create a larger dataset
d2 <- d[sample(1:3,1e6,TRUE),]
# benchmark
library(microbenchmark)
microbenchmark(
  docp = do.call(paste, c(d2[cols], sep="-")),
  appl = apply( d2[, cols ] , 1 , paste , collapse = "-" ),
  tidr = tidyr::unite_(d2, "x", cols, sep="-")$x,
  docs = do.call(sprintf, c(d2[cols], '%s-%s-%s')),
  times=10)

使用数据:

d <- data.frame(a = 1:3, b = c('a','b','c'), c = c('d','e','f'), d = c('g','h','i')) 

d这里有一种非常非常规(但快速)的方法:使用
fwrite
from
data.table
将列“粘贴”在一起,然后使用
frad
将其读回。为了方便起见,我将这些步骤编写为一个名为
fpaste
的函数:

fpaste <- function(dt, sep = ",") {
  x <- tempfile()
  fwrite(dt, file = x, sep = sep, col.names = FALSE)
  fread(x, sep = "\n", header = FALSE)
}

fpaste这里有一个相当非常规(但快速)的方法:使用
fwrite
from
data.table
将列“粘贴”在一起,然后使用
fread
将其读回。为了方便起见,我将这些步骤编写为一个名为
fpaste
的函数:

fpaste <- function(dt, sep = ",") {
  x <- tempfile()
  fwrite(dt, file = x, sep = sep, col.names = FALSE)
  fread(x, sep = "\n", header = FALSE)
}

fpaste我知道这是一个老问题,但我认为我应该按照提问者的建议,使用paste()函数给出简单的解决方案:

data_1<-data.frame(a=data$a,"x"=paste(data$b,data$c,data$d,sep="-")) 
data_1
  a     x
1 1 a-d-g
2 2 b-e-h
3 3 c-f-i

data\u 1我知道这是一个老问题,但我认为我应该按照提问者的建议,使用paste()函数给出简单的解决方案:

data_1<-data.frame(a=data$a,"x"=paste(data$b,data$c,data$d,sep="-")) 
data_1
  a     x
1 1 a-d-g
2 2 b-e-h
3 3 c-f-i

data\u 1请注意,如果要将
a
列以外的所有列粘贴在一起,您可能需要使用
d[,name(d)!=“a']
,而不是
d[,cols]
列。作为一种标准解决方案,我认为您可以将其缩短为
cbind(a=d['a'],x=do.call(粘贴,c(d[cols],sep='-'))
,例如,在使用
cbind的
data.frame
方法时,避免使用逗号、
list
data.frame
。请注意,您可能希望使用
d[,name(d)!=“a'”而不是
d[,cols]
如果除了
a
列以外的所有列都要粘贴在一起,那么我认为你可以将其缩短为
cbind(a=d['a'],x=do.call(粘贴,c(d[cols],sep='-'))
,例如,避免使用逗号、
list
data.frame