这是我的数据,
v11 <- c("00240031", "00310028")
v12 <- c("00000000", "00000000")
v13 <- c("00310064", "00180058")
data <- data.frame(v11, v12, v13)
data <- lapply(data, as.character)
testdata <- as.data.frame(data, stringsAsFactors = F)
testdata[testdata == '0'] <- '000000000'
testdata我想将每一列(从v11开始到v99)分成两列。我使用substr对第一列进行这样的拆分,
transform(v11, v11_a = substr(v11, 1, 4), v11_b = substr(v11, 5, 8))
X_data v11_a v11_b
1 00240031 0024 0031
2 00310028 0031 0028除了X_data列之外,看起来很好。我不想让它出现在输出中。有什么更好的方法吗?
tidyr::separate将不适用,因为我的数据是字符类型?
v11 %>% separate(v11, into = c('v11_a', 'v11_b'), sep = 4)
Error in UseMethod("separate_") :
no applicable method for 'separate_' applied to an object of class "character"第二,如何对后续列(例如v11到v99)重复这个过程?
理想情况下,在拆分并转换为数字类型之后,我的最终数据应该如下所示,
> dataf
v11_a v11_b v12_a v12_b v13_a v13_b
1 24 31 0 0 31 64
2 31 28 0 0 18 58评论:
这是令人惊讶的是,你是如此迅速地提出惊人的解决方案。谢谢你们所有人。
发布于 2019-01-16 10:51:38
在base R中,可以通过循环遍历列,用分隔符,替换非零之间的0's,读入data.frame (read.table),并将数据集的list替换为cbind。
lst1 <- lapply(testdata, function(x) {
x1 <- read.table(text = sub("(?<=[1-9])0+", ",", x, perl = TRUE),
header = FALSE, sep=",", col.names = c('a', 'b'), fill = TRUE)
replace(x1, is.na(x1), 0)})
do.call(cbind, lst1)
# v11.a v11.b v12.a v12.b v13.a v13.b
#1 24 31 0 0 31 64
#2 31 28 0 0 18 58它也可以用tidyverse完成,方法是先将gather转换为'long‘格式,然后执行separate离子,最后将其返回到“wide”格式。
library(tidyverse)
gather(testdata) %>%
separate(value, into = c('a', 'b'), sep=4, convert = TRUE) %>%
gather(key1, val, a:b) %>%
unite(key, key, key1, sep="_") %>%
group_by(key) %>%
mutate(ind = row_number()) %>%
spread(key, val) %>%
select(-ind)
# A tibble: 2 x 6
# v11_a v11_b v12_a v12_b v13_a v13_b
# <int> <int> <int> <int> <int> <int>
#1 24 31 0 0 31 64
#2 31 28 0 0 18 58或者另一个选择是将summarise_all与read.table结合使用。
testdata %>%
summarise_all(funs(list(read.table(text =sub("^(....)", "\\1 ", .),
header = FALSE)))) %>%
unnest发布于 2019-01-16 11:02:23
下面是一个使用非常方便的操作library(splitstackshape)的想法,
library(splitstackshape)
cSplit(setDT(testdata)[, lapply(.SD, function(i) gsub("(.{4})", "\\1 ", i))], names(testdata), sep = ' ')
# v11_1 v11_2 v12_1 v12_2 v13_1 v13_2
#1: 24 31 0 0 31 64
#2: 31 28 0 0 18 58发布于 2019-01-16 11:07:57
有些人在data.table中游玩,并重用现有的substr()逻辑:
library(data.table)
setDT(testdata)
cols <- paste0("v", 11:13)
new_cols <- paste0(rep(cols, 2), rep(c("a", "b"), each = length(cols)))
extra <- function(x) substr(x, 1, 4)
extrb <- function(x) substr(x, 5, 8)
testdata[, (new_cols) := c(lapply(.SD, extra), lapply(.SD, extrb)), .SDcols = cols]
> testdata
v11 v12 v13 v11a v12a v13a v11b v12b v13b
1: 00240031 00000000 00310064 0024 0000 0031 0031 0000 0064
2: 00310028 00000000 00180058 0031 0000 0018 0028 0000 0058https://stackoverflow.com/questions/54215213
复制相似问题