我的csv数据文件格式如下:
DF %>%
mutate(Merged = gsub("^,+|,+$", "", gsub(",{2,}", ",",
do.call(paste, c(., list(sep=",")))))) %>%
separate_rows(Merged, sep=",\\s*")
我想在R
中得到如下结果1:
101
102
2:
103
104
105
3:
106
107
我使用了for循环,但需要很多时间。原始数据3MB文件。
添加了额外的列" m_id"在test_data数据框中并在代码下执行。
Value id
101 1
102 1
103 2
104 2
105 2
106 3
107 3
如何在没有for循环的情况下达到上述要求?
答案 0 :(得分:0)
我们可以使用phantastic tidyverse
包含一些逻辑:
library(tidyverse)
junk = "
1:
101
102
2:
103
104
105
3:
106
107"
df <- data_frame(text=junk)
df %>%
separate_rows(text, sep = '\n') %>%
filter(text != "") %>%
extract(text, into = c('group'), regex = "^(\\d+):", remove = FALSE) %>%
fill(group) %>%
filter(!grepl("^\\d+:", text)) %>%
select(group, text)
<小时/> 这产生了
# A tibble: 7 x 2
group text
<chr> <chr>
1 1 101
2 1 102
3 2 103
4 2 104
5 2 105
6 3 106
7 3 107
答案 1 :(得分:0)
也会起作用:
df <- read.table(col.names = "x",
stringsAsFactors = FALSE,
text = "1:
101
102
2:
103
104
105
3:
106
107")
retain <- function(x) {
res <- rep(NA, length(x))
for (i in seq_along(x)) {
if (grepl(":", x[i])) {
res[i] <- x[i]
} else {
res[i] <- res[i-1]
}
}
return(res)
}
df$id <- retain(df$x)
df <- subset(df, id != x)
df$id <- as.numeric(gsub(":", "", df$id))
df
答案 2 :(得分:0)
这是另一个tidyverse
解决方案:
library(tidyverse)
df %>%
mutate(id = str_detect(V1, ":"),
id = case_when(id == TRUE ~ V1)) %>%
fill(id) %>%
filter(V1 != id) %>%
mutate(id = str_extract(id, "^(\\d+)"))
V1 id 1 101 1 2 102 1 3 103 2 4 104 2 5 105 2 6 106 3 7 107 3
我们也可以这样做:
df %>%
mutate(id = str_extract(V1, "^(\\d+):"),
id = str_extract(id, "^(\\d+)")) %>%
fill(id) %>%
mutate(V1 = str_replace(V1, "^(\\d+):", NA_character_)) %>%
drop_na()
数据:
df <- read.table(text = "1:
101
102
2:
103
104
105
3:
106
107", stringsAsFactor = F)