将每个“X”列粘贴到数据框中的单个列

时间:2014-02-21 23:57:01

标签: r dataframe paste

我有超过100列和150行的dfrm。我需要将每4列的内容合并为1(最好用“/”分隔,虽然可有可无),这很简单,执行apply(dfrm[ ,1:4], 1, paste, collapse="/")。我很难将解决方案扩展到我的整个df。换句话说:

我怎么能这样做:

        loc1   loc1.1 loc1.2 loc1.3 loc2  loc2.1 loc2.2  loc2.3
ind.1    257    262    228    266    204    245    282    132
ind.2    244    115    240    187    196    133    189    251
ind.3    298    139    216    225    219    276    192    254
ind.4    129    176    180    182    215    250    227    186
ind.5    238    217    284    240    131    184    247    168

对于这样的事情:

                 loc1            loc2
ind.1 257/262/228/266 204/245/282/132
ind.2 244/115/240/187 196/133/189/251
ind.3 298/139/216/225 219/276/192/254
ind.4 129/176/180/182 215/250/227/186
ind.5 238/217/284/240 131/184/247/168

在超过100行和列的数据框中。我已尝试将数据框编入索引,如this question解决方案中所示,但在创建每4列的索引后,确实发现自己在尝试对我的数据帧执行do.call时丢失了。我确信必须有一个简单的解决方案,但请记住,我只是精通R.

也;如果正文处于形状状态,则字母名称不是真正的问题,因为提取名称列表由loc <- colnames(dfrm)loc <- loc[c(T, F, F, F)执行,然后定义colnames(dfrm) <- loc,但如果合并则会很好。

4 个答案:

答案 0 :(得分:5)

这当然不是很好,但它有效:

do.call(cbind, lapply(1:ceiling(ncol(df)/4), function(i)
                      apply(df[,seq(4*(i-1)+1, min(4*i, ncol(df))), drop = F],
                            1, paste, collapse = "/")))
#      [,1]              [,2]             
#ind.1 "257/262/228/266" "204/245/282/132"
#ind.2 "244/115/240/187" "196/133/189/251"
#ind.3 "298/139/216/225" "219/276/192/254"
#ind.4 "129/176/180/182" "215/250/227/186"
#ind.5 "238/217/284/240" "131/184/247/168"

当列数不能被4整除时,ceilingdrop可以存在边缘情况。另外,请注意最终结果是matrix(感谢apply),如果您愿意,可以将其转换回data.frame(并指定任何列名称)。

答案 1 :(得分:3)

参加派对的方式较晚,但我认为这有点清洁(对于4列数的非倍数而言非常稳健):

as.data.frame(
  lapply(
    split.default(df, (1:ncol(df) - 1) %/% 4), 
    function(x) do.call(paste, c(x, list(sep="/"))
) ) )

使用(1:ncol(df) - 1) %/% 4)按列拆分数据框会创建包含四列的组(如果最后一组有四列的非多数,则会更少),这样就可以轻松传递给{{1 }}。请注意,我们必须使用paste,因为split.default将尝试按行而不是列进行拆分。生产:

split.data.frame

答案 2 :(得分:0)

可能会更快。

 df = data.frame(c1 =letters,c2=LETTERS, c3=letters, c4=LETTERS)
 do.call('paste',c(df[,1:2],list(sep='/')));
 [1] "A/a" "B/b" "C/c" "D/d" "E/e" "F/f" "G/g" "H/h" "I/i" "J/j" "K/k" "L/l"
 [13] "M/m" "N/n" "O/o" "P/p" "Q/q" "R/r" "S/s" "T/t" "U/u" "V/v" "W/w" "X/x"
 [25] "Y/y" "Z/z"
 do.call('paste',c(df[,3:4],list(sep='/')));
 [1] "A/a" "B/b" "C/c" "D/d" "E/e" "F/f" "G/g" "H/h" "I/i" "J/j" "K/k" "L/l"
 [13] "M/m" "N/n" "O/o" "P/p" "Q/q" "R/r" "S/s" "T/t" "U/u" "V/v" "W/w" "X/x"
 [25] "Y/y" "Z/z"

答案 3 :(得分:0)

这是(希望)一个更通用的解决方案,它不依赖于任何位置参数:

newnames <- gsub("\\.\\d+","",names(df))
#[1] "loc1" "loc1" "loc1" "loc1" "loc2" "loc2" "loc2" "loc2"
do.call(cbind,
        lapply(unique(newnames), function(x) 
          do.call(paste,c(df[newnames %in% x],sep="/") )
        )
)

#     [,1]              [,2]             
#[1,] "257/262/228/266" "204/245/282/132"
#[2,] "244/115/240/187" "196/133/189/251"
#[3,] "298/139/216/225" "219/276/192/254"
#[4,] "129/176/180/182" "215/250/227/186"
#[5,] "238/217/284/240" "131/184/247/168"