我觉得我的情况是实验中的典型用例,其中数据记录为文本文件,供人类理解,而不是机器消耗。标签会散布在实际数据中,以描述随后的数据。对于数据分析,标记需要与数据行集成在一起才有用。下面是一个虚构的示例。
TAG1, t1_1 DATA_A, 5, 3, 4, 8 DATA_A, 3, 4, 5, 7 TAG1, t1_2 TAG2, t2_1 DATA_B, 1, 2, 3, 4, 5 DATA_A, 1, 2, 3, 4
所需的解析结果应为两个数据帧。一个用于DATA_A,
X1, X2, X3, X4, TAG1, TAG2 5, 3, 4, 8, t1_1, NA 3, 4, 5, 7, t1_1, NA 1, 2, 3, 4, t1_2, t2_1
和一个用于DATA_B
X1, X2, X3, X4, X5, TAG1, TAG2 1, 2, 3, 4, 5, t1_2, t2_1
当前方法(在Python中实现)逐行检查文件。如果以“ T”开头,则更新相应的变量。如果以“ DATA”开头,则将标记值附加到“ DATA”行的末尾,并将现在完成的行附加到相应的CSV文件。最后,将CSV文件读入数据帧以进行数据分析。
我想知道是否可以一步一步完成此数据导入。我想到的是
library(tidyverse)
text_frame <- read_lines(clipboard(), skip_empty_rows = TRUE) %>%
enframe(name = NULL, value = "line")
text_frame %>%
separate(line, into = c("ID", "value"), extra = "merge", sep = ", ")
产生
# A tibble: 7 x 2
ID value
<chr> <chr>
1 TAG1 t1_1
2 DATA_A 5, 3, 4, 8
3 DATA_A 3, 4, 5, 7
4 TAG1 t1_2
5 TAG2 t2_1
6 DATA_B 1, 2, 3, 4, 5
7 DATA_A 1, 2, 3, 4
下一步是创建新列“ TAG1”和“ TAG2”,并将值添加到该行。这就是我卡住的地方。各个行就像gather
。我该怎么办?通用方法是否合理?有什么建议吗?
欢迎快速/内存高效的解决方案,因为我需要处理数百个〜10MB的文本文件(它们具有相同的结构)。
答案 0 :(得分:0)
使用输入数据
text <- '
TAG1, t1_1
DATA_A, 5, 3, 4, 8
DATA_A, 3, 4, 5, 7
TAG1, t1_2
TAG2, t2_1
DATA_B, 1, 2, 3, 4, 5
DATA_A, 1, 2, 3, 4
'
您可以通过选择V2
的元素(其中第一列V2
是TAG [1 | 2])从导入数据V1
的第二列中获取标签,然后执行每个组。组由变量标识,从0开始,每次出现[V1包含TAG,然后V1不包含TAG]后,递增1。
然后将标记作为自己的列,您可以删除TAG行,并根据第一列是否包含'B'
library(data.table)
df <- fread(text, fill = T, blank.lines.skip = T)
df[, `:=`(TAG1 = V2[V1 == 'TAG1'],
TAG2 = V2[V1 == 'TAG2']),
by = .(g = (rleid(grepl('TAG', V1)) - 1) %/% 2)]
df <- df[-grep('TAG', V1)]
split(df, df[, grepl('B', V1)])
# $`FALSE`
# V1 V2 V3 V4 V5 V6 TAG1 TAG2
# 1: DATA_A 5 3 4 8 NA t1_1 <NA>
# 2: DATA_A 3 4 5 7 NA t1_1 <NA>
# 3: DATA_A 1 2 3 4 NA t1_2 t2_1
#
# $`TRUE`
# V1 V2 V3 V4 V5 V6 TAG1 TAG2
# 1: DATA_B 1 2 3 4 5 t1_2 t2_1
如果您不一定总是使用2个标记,并且可能有更多或更少的标记,则可以将上面fread
之后的步骤替换为
n_tags <- df[, as.numeric(gsub('[^0-9]', '', max(grep('TAG', V1, value = T))))]
df[, g := (rleid(grepl('TAG', V1)) - 1) %/% 2]
for(i in seq_len(n_tags))
df[, paste0('TAG', i) := V2[V1 == paste0('TAG', i)], g]