我有一些大数据文件需要解析。每个文件都重复某些标记,但只有一个标记重复。例如,每个文件都有name
和date
的父级,这些父级只在每个数据块中显示一次但有许多子项,例如patent citations
,non-patent citations
和{{1} }。
因此,我通过查找这三个子节点的所有案例进行解析,并将每个文件中父节点的每次迭代存储到各个列表中。问题是这些孩子的长度总是不同,我想把它们全部写在CSV文件的一行上。
例如,对于我的列表输入的文件中的一次迭代,就像:
classification
我希望写入CSV文件的输出看起来像:
Name = [Jon]
Date = [1985]
Patcit = [1, 2, 3]
Npatcit = [4, 5, 6, 7, 8]
Class = [9, 10]
我的代码贯穿以下文件:
Name Date Patcit Npatcit Class
Jon 1985 1 4 9
2 5 10
3 6
7
8
(Repeat next name and date iteration on the next row)
然后,例如,仅为 Patcit 列表编写内容将类似于:
from bs4 import BeautifulSoup
soup = BeautifulSoup(data, "lxml")
grant = soup.findAll("grant")
for info in grant:
cite = soup.findAll("us-citation")
names = soup.findAll("name")
Patcit = []
Npatcit = []
Class = []
for item2 in cite:
for items in item2.findAll("patcit"):
pat = items.find("patent-citation-title")
Patcit.append(pat)
.
.
.
.
The same for the other 2 lists
使用for inv_name in zip(names):
for j in range(int(len(Patcit))):
datapatcit = Patcit[j]
writer.writerow[(inv_name).text, datapatcit]
所以这就是问题所在。我无法找到一个很好的方法来获得输出我想要的方式。
答案 0 :(得分:2)
在每个输入中建立最长列表后,您可以使用空字符串填充其他列表。
Name = ["Jon"]
Date = [1985]
Patcit = [1, 2, 3]
Npatcit = [4, 5, 6, 7, 8]
Class = [9, 10]
data = {"Name":Name, "Date":Date, "Patcit":Patcit, "Npatcit":Npatcit, "Class":Class}
max_n = max([len(x) for x in data.values()])
for field in data:
data[field] += [''] * (max_n - len(data[field]))
data
{'Class': [9, 10, '', '', ''],
'Date': [1985, '', '', '', ''],
'Name': ['Jon', '', '', '', ''],
'Npatcit': [4, 5, 6, 7, 8],
'Patcit': [1, 2, 3, '', '']}
然后使用您首选的方法写入CSV。我选择熊猫:
import pandas as pd
df = pd.DataFrame(data)
df.to_csv("output.csv", index=False)
df
Class Date Name Npatcit Patcit
0 9 1985 Jon 4 1
1 10 5 2
2 6 3
3 7
4 8
<强>更新强>
如果您需要在多次迭代中执行此操作(例如,在示例用例中info
中的多个grant
个案例),则可以使用concat
。
我还建议将填充操作移动到一个函数中,如下所示:
import pandas as pd
def pad(data):
max_n = max([len(x) for x in data.values()])
for field in data:
data[field] += [''] * (max_n - len(data[field]))
return data
# CSV 1
Name = ["Jon"]
Date = [1985]
Patcit = [1, 2, 3]
Npatcit = [4, 5, 6, 7, 8]
Class = [9, 10]
data = {"Name":Name, "Date":Date, "Patcit":Patcit, "Npatcit":Npatcit, "Class":Class}
df = pd.DataFrame(pad(data))
# CSV 2
Name = ["Sally"]
Date = [19995]
Patcit = [9,8,7]
Npatcit = [1,3,5]
Class = [4, 10,15]
data = {"Name":Name, "Date":Date, "Patcit":Patcit, "Npatcit":Npatcit, "Class":Class}
df = pd.concat([df, pd.DataFrame(pad(data))])
df
Class Date Name Npatcit Patcit
0 9 1985 Jon 4 1
1 10 5 2
2 6 3
3 7
4 8
0 4 19995 Sally 1 9
1 10 3 8
2 15 5 7
答案 1 :(得分:0)
在实现pandas
之后,我在循环的开头添加了一个简单的计数器,并在主循环中使用if语句运行@andrew_reece给出的函数pad(data)
,如下所示:
counter == 0
main for loop in grant:
lists = []
.
.
.
def pad(data):
.
.
.
if counter == 0:
df = pd.DataFrame(pad(data))
else:
df = pd.concat([df, pd.DataFrame(pad(data))])
counter = counter + 1
我们也可以使用True
或False
语句代替'count'。这可以确保第一个解析能够“触发”第一个连接。
再次感谢@andrew_reece的帮助。