在 R 中粘贴 5 列组的问题
Issue with pasting 5 columns groups in R
我有如下数据 table。所有列都是字符。
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 中实现这一点。感谢任何帮助。
谢谢。
稍微扩展一下您的数据:
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
,按 行,而不是列,所以我们使用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
对每个帧进行 处理 ,return 简化(在本例中)。 (如果我们指定 simplify=FALSE
或者如果不是所有的长度都相同,那么它将被 return 未简化,作为 list
而不是 vector
)。 =25=]
我们应用于每个帧的函数是 apply(., 1, paste0, collapse0)
它将 return 5 列粘贴的向量,类似于:
apply(s, 1, paste0, collapse = "")
# $`0`
# [1] ""044N005E026" "044N005E026""
因为我们想把它们合并起来,所以我们把它围成paste(apply(...), collapse = "-")
。
使用注释末尾定义的 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
或使用注释中的 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
如果根据评论,你想使用 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")
我有如下数据 table。所有列都是字符。
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 中实现这一点。感谢任何帮助。
谢谢。
稍微扩展一下您的数据:
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
,按 行,而不是列,所以我们使用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
对每个帧进行 处理 ,return 简化(在本例中)。 (如果我们指定simplify=FALSE
或者如果不是所有的长度都相同,那么它将被 return 未简化,作为list
而不是vector
)。 =25=]我们应用于每个帧的函数是
apply(., 1, paste0, collapse0)
它将 return 5 列粘贴的向量,类似于:apply(s, 1, paste0, collapse = "") # $`0` # [1] ""044N005E026" "044N005E026""
因为我们想把它们合并起来,所以我们把它围成
paste(apply(...), collapse = "-")
。
使用注释末尾定义的 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
或使用注释中的 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
如果根据评论,你想使用 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")