我有超过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
,但如果合并则会很好。
答案 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整除时,ceiling
和drop
可以存在边缘情况。另外,请注意最终结果是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"