XML 数据扁平化,如何找回原始数据
XML Data flatten, how to get the original data back
我有一个包含以下示例数据的 txt 文件:
id,001
v1,some_value
id,002
v1,some_value
v2,some_value
id,003
v2,some_value
id,004
v4,some_value
原始数据具有xml结构。它被压平了。所以值的顺序很重要。
实际上,变量的数量很大(超过 1000 个)。并且存在嵌套结构:v1 可以是 v2 的父类别。我们在另一个文件中有此信息。
我的问题是:给定这个展平结构,我们怎样才能用 R 或 python 取回原始 xml 数据?
其实最后我想把这些值转换成结构化的表格数据,列有:id,v1,v2,v3等。所以如果先搞定这种格式比较简单,也是可以的。然后我们不需要嵌套结构变量来进行转换,而只需要按顺序排列的可能变量列表。假设对于上面的示例,我们有变量:v1、v2、v3 和 v4。所以最终数据将是:
[更新]:变量的顺序对于恢复原始数据很重要。
例如,如果我们有:
id,001
v1,some_value
id,002
v2,some_value
v1,some_value
id,003
v2,some_value
id,004
v4,some_value
那么,我们会得到:
您提到您在另一个文件中有现有字段。前提是您可以使用这些来制作一个命名的空白字符向量,如下所示:
existing_list <- c(id = "", v1 = "", v2 = "", v3 = "", v4 = "")
那么你可以这样做:
df <- read.csv(text = "my_textfile.csv", header = FALSE)
id_list <- split(df, cumsum(df$V1 == "id"))
do.call(rbind, lapply(id_list, function(x) {
vec <- setNames(x$V2, x$V1)
existing_list[match(names(vec), names(existing_list))] <- vec
as.data.frame(as.list(existing_list))
}))
#> id v1 v2 v3 v4
#> 1 001 some_value
#> 2 002 some_value some_value
#> 3 003 some_value
#> 4 004 some_value
同样,这里没有使用外部包。
这是一种方法 Python。
假设输入文件'flattened_xml.txt'
包含:
id,001
v1,some_value1
id,002
v2,some_value2
v1,some_value3
id,003
v2,some_value4
id,004
v4,some_value5
代码:
# Get lines of text file.
with open('flattened_xml.txt') as file:
data = file.read().splitlines()
# Determine what fiels are present.
fields = []
for line in data:
id, _ = line.split(',')
if id not in fields:
fields.append(id)
table = [{field:field for field in fields}] # Header row.
row = {}
for line in data:
field, value = line.split(',')
if field == fields[0]:
row = {field: value}
row.update({key: None for key in fields[1:]})
continue
row.update({key: value if key == field else None for key in fields[1:]})
table.append(row)
row = {key: None for key in fields}
for row in table:
s = [f'{value if value is not None else "":11}' for value in row.values()]
print('|' + '|'.join(s) + '|')
结果:
|id |v1 |v2 |v4 |
|001 |some_value1| | |
|002 | |some_value2| |
| |some_value3| | |
|003 | |some_value4| |
|004 | | |some_value5|
我有一个包含以下示例数据的 txt 文件:
id,001
v1,some_value
id,002
v1,some_value
v2,some_value
id,003
v2,some_value
id,004
v4,some_value
原始数据具有xml结构。它被压平了。所以值的顺序很重要。
实际上,变量的数量很大(超过 1000 个)。并且存在嵌套结构:v1 可以是 v2 的父类别。我们在另一个文件中有此信息。
我的问题是:给定这个展平结构,我们怎样才能用 R 或 python 取回原始 xml 数据?
其实最后我想把这些值转换成结构化的表格数据,列有:id,v1,v2,v3等。所以如果先搞定这种格式比较简单,也是可以的。然后我们不需要嵌套结构变量来进行转换,而只需要按顺序排列的可能变量列表。假设对于上面的示例,我们有变量:v1、v2、v3 和 v4。所以最终数据将是:
[更新]:变量的顺序对于恢复原始数据很重要。
例如,如果我们有:
id,001
v1,some_value
id,002
v2,some_value
v1,some_value
id,003
v2,some_value
id,004
v4,some_value
那么,我们会得到:
您提到您在另一个文件中有现有字段。前提是您可以使用这些来制作一个命名的空白字符向量,如下所示:
existing_list <- c(id = "", v1 = "", v2 = "", v3 = "", v4 = "")
那么你可以这样做:
df <- read.csv(text = "my_textfile.csv", header = FALSE)
id_list <- split(df, cumsum(df$V1 == "id"))
do.call(rbind, lapply(id_list, function(x) {
vec <- setNames(x$V2, x$V1)
existing_list[match(names(vec), names(existing_list))] <- vec
as.data.frame(as.list(existing_list))
}))
#> id v1 v2 v3 v4
#> 1 001 some_value
#> 2 002 some_value some_value
#> 3 003 some_value
#> 4 004 some_value
同样,这里没有使用外部包。
这是一种方法 Python。
假设输入文件'flattened_xml.txt'
包含:
id,001
v1,some_value1
id,002
v2,some_value2
v1,some_value3
id,003
v2,some_value4
id,004
v4,some_value5
代码:
# Get lines of text file.
with open('flattened_xml.txt') as file:
data = file.read().splitlines()
# Determine what fiels are present.
fields = []
for line in data:
id, _ = line.split(',')
if id not in fields:
fields.append(id)
table = [{field:field for field in fields}] # Header row.
row = {}
for line in data:
field, value = line.split(',')
if field == fields[0]:
row = {field: value}
row.update({key: None for key in fields[1:]})
continue
row.update({key: value if key == field else None for key in fields[1:]})
table.append(row)
row = {key: None for key in fields}
for row in table:
s = [f'{value if value is not None else "":11}' for value in row.values()]
print('|' + '|'.join(s) + '|')
结果:
|id |v1 |v2 |v4 |
|001 |some_value1| | |
|002 | |some_value2| |
| |some_value3| | |
|003 | |some_value4| |
|004 | | |some_value5|