我有如下数据表。所有列均以字符为单位。
Table:
V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 .... V69
044 N 005 E 026 044 N 006 E 011
我想将它们粘贴到从V29开始的5个列组中。例如,我想在Table
中获得一个输出列,如下所示。
Table:
V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 .... V69 Output
044 N 005 E 026 044 N 006 E 011 044N005E026-044N006E011-
如何在R中实现这一目标。感谢您的帮助。
谢谢。
答案 0 :(得分:1)
稍微扩展数据:
x <- read.table(stringsAsFactors=FALSE, header=TRUE, as.is=TRUE, colClasses="character", text="
V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 V29a V30a V31a V32a V33a V34a V35a V36a V37a V38a
044 N 005 E 026 044 N 006 E 011 044 N 005 E 026 044 N 006 E 011
044 N 005 E 026 044 N 006 E 011 044 N 005 E 026 044 N 006 E 011 ")
答案:
sapply(split.default(x, (seq_len(ncol(x))-1) %/% 5),
function(s) paste(apply(s, 1, paste0, collapse = ""), collapse = "-"))
# 0 1 2
# "044N005E026-044N005E026" "044N006E011-044N006E011" "044N005E026-044N005E026"
# 3
# "044N006E011-044N006E011"
可以很容易地将其分配给同一帧的一列。
说明:
将一帧分解为5列,我想到了split
,但是默认使用split(...)
将使用split.data.frame
,它会按行,而不是 column ,因此我们使用split.default
(按列工作)。从那里,您可以看到我们如何对事物进行分组:
(seq_len(ncol(x))-1) %/% 5
# [1] 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
对于每个组,我们得到一个5列的框架:
split.default(x, (seq_len(ncol(x))-1) %/% 5)
# $`0`
# V29 V30 V31 V32 V33
# 1 44 N 5 E 26
# 2 44 N 5 E 26
# $`1`
# V34 V35 V36 V37 V38
# 1 44 N 6 E 11
# 2 44 N 6 E 11
### truncated for brevity
因此,我们使用sapply
对这些帧中的每一个做某事,并将其简化返回(在这种情况下)。 (如果我们指定simplify=FALSE
,或者如果它们的长度都不相同,那么它将以list
而不是vector
的形式返回,不做简单化。)
我们应用于每帧的函数是apply(., 1, paste0, collapse0)
,它将返回5列粘贴的向量,例如:
apply(s, 1, paste0, collapse = "")
# $`0`
# [1] ""044N005E026" "044N005E026""
由于我们希望将它们组合在一起,因此将其用paste(apply(...), collapse = "-")
包围。
答案 1 :(得分:1)
使用结尾处的注释中定义的DF
创建一个sprintf
格式字符串fmt
,然后运行它。
如果DF
中有NA,则它们将在输出中显示为字符串"NA"
。如果您希望完全省略它们,则在运行下面的代码之前,将它们替换为DF
中的空字符串,即先运行DF[is.na(DF)] <- ""
。
fmt <- paste(rep(strrep("%s", 5), ncol(DF)/5), collapse = "-") # %s%s%s%s%s-%s%s%s%s%s
Output <- do.call("sprintf", c(fmt, DF))
data.frame(DF, Output, stringsAsFactors = FALSE)
给予:
V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 Output
1 044 N 005 E 026 044 N 006 E 011 044N005E026-044N006E011
或使用Note中的DF2
代替DF
,我们得到:
V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 Output
1 044 N 005 E 026 044 N 006 E 011 044N005E026-044N006E011
2 045 S 006 F 027 045 S 007 F 012 045S006F027-045S007F012
如果根据评论,您想使用data.table,则使用它(上面的fmt
):
library(data.table)
DT <- data.table(DF)
DT[, Output:=do.call("sprintf", c(fmt, .SD))]
Lines <- "
V29 V30 V31 V32 V33 V34 V35 V36 V37 V38
044 N 005 E 026 044 N 006 E 011 "
DF <- read.table(text = Lines, header = TRUE, colClasses = "character")
Lines2 <- "
V29 V30 V31 V32 V33 V34 V35 V36 V37 V38
1 044 N 005 E 026 044 N 006 E 011
2 045 S 006 F 027 045 S 007 F 012"
DF2 <- read.table(text = Lines2, header = TRUE, colClasses = "character")