我有一个txt文件,其中包含这种格式的数据。前三行重复一遍又一遍。
name=1
grade=A
class=B
name=2
grade=D
class=A
我想以表格格式输出数据,例如:
name | grade | class
1 | A | B
2 | D | A
我正在努力设置标题并仅循环访问数据。到目前为止,我尝试过的是:
def myfile(filename):
with open(file1) as f:
for line in f:
yield line.strip().split('=',1)
def pprint_df(dframe):
print(tabulate(dframe, headers="keys", tablefmt="psql", showindex=False,))
#f = pd.DataFrame(myfile('file1')
df = pd.DataFrame(myfile('file1'))
pprint_df(df)
输出是
+-------+-----+
| 0 | 1 |
|-------+-----|
| name | 1 |
| grade | A |
| class | B |
| name | 2 |
| grade | D |
| class | A |
+-------+-----+
不是我真正想要的东西。
答案 0 :(得分:9)
您可以使用熊猫读取文件并处理数据。您可以使用此:
import pandas as pd
df = pd.read_table(r'file.txt', header=None)
new = df[0].str.split("=", n=1, expand=True)
new['index'] = new.groupby(new[0])[0].cumcount()
new = new.pivot(index='index', columns=0, values=1)
new
输出:
0 class grade name
index
0 B A 1
1 A D 2
答案 1 :(得分:7)
我知道您有足够的答案,但这是使用字典的另一种方法:
import pandas as pd
from collections import defaultdict
d = defaultdict(list)
with open("text_file.txt") as f:
for line in f:
(key, val) = line.split('=')
d[key].append(val.replace('\n', ''))
df = pd.DataFrame(d)
print(df)
这将为您提供输出:
name grade class
0 1 A B
1 2 D A
只是换个角度来看。
答案 2 :(得分:3)
您还可以执行以下操作:以3块为单位读取文本文件file
,构建一个嵌套列表,然后将其放入数据框:
from itertools import zip_longest
import pandas as pd
# taken from https://docs.python.org/3.7/library/itertools.html:
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
data = [['name', 'grade', 'class']]
with open(file, 'r') as fobj:
blocks = grouper(fobj, 3)
for b in blocks:
data.append([i.split('=')[-1].strip() for i in b])
df = pd.DataFrame(data[1:], columns=data[0])
df
将直接是
name grade class
0 1 A B
1 2 D A
注释#1:尽管比纯pandas
解决方案需要更多的代码行,但根据我的经验,由于使用的{{1} }从而减少了开销。
注释#2:通常,我认为最好以其他格式存储输入数据,例如pandas
或json
。这样会更容易阅读,例如使用csv文件的csv
函数read_csv。
答案 3 :(得分:3)
当您获得输出时,这就是我如何处理该问题:
首先根据列的可重复性创建唯一索引,
setDT(df1)
df1[, .N, names(df1)]
# x y N
# 1: a a 1
# 2: b b 2
# 3: c c 3
然后我们使用df['idx'] = df.groupby(df['0'])['0'].cumcount() + 1
print(df)
0 1 idx
0 name 1 1
1 grade A 1
2 class B 1
3 name 2 2
4 grade D 2
5 class A 2
函数使用它来旋转数据框
crosstab
答案 4 :(得分:2)
此解决方案假定文本格式与您所描述的相同,但是您可以对其进行修改以使用其他单词来表示新行的开头。在此,我们假设新行以name
字段开头。我在下面修改了您的myfile()
函数,希望它能给您一些想法:)
def myfile(filename):
d_list = []
with open(filename) as f:
d_line = {}
for line in f:
split_line = line.rstrip("\n").split('=') # Strip \n characters and split field and value.
if (split_line[0] == 'name'):
if d_line:
d_list.append(d_line) # Append if there is previous line in d_line.
d_line = {split_line[0]: split_line[1]} # Start a new dictionary to collect the next lines.
else:
d_line[split_line[0]] = split_line[1] # Add the other 2 fields to the dictionary.
d_list.append(d_line) # Append the last line.
return pd.DataFrame(d_list) # Turn the list of dictionaries into a DataFrame.
答案 5 :(得分:0)
您可以使用 Python的Dictionary模块和Pandas生成该输出。
import pandas as pd
from collections import defaultdict
text = '''name=1
grade=A
class=B
name=2
grade=D
class=A'''
text = text.split()
new_dict = defaultdict(list)
for i in text:
temp = i.split('=')
new_dict[temp[0]].append(temp[1])
df = pd.DataFrame(new_dict)
这种方法可能不是最有效的方法,但是它没有使用Pandas的任何高级功能。希望对您有所帮助。
输出:
name grade class
0 1 A B
1 2 D A
答案 6 :(得分:0)
恕我直言,目前所有的答案看起来都太复杂了。我要做的是使用'='
作为pd.read_csv
的sep
参数来读取2列,然后pivot
获得的DataFrame:
import pandas as pd
df = pd.read_csv('myfile', sep='=', header=None)
# 0 1
# 0 name 1
# 1 grade A
# 2 class B
# 3 name 2
# 4 grade D
# 5 class A
df = df.pivot(index=df.index // len(df[0].unique()), columns=0)
# 1
# 0 class grade name
# 0 B A 1
# 1 A D 2
如果您不希望该多级列索引出现在结果中,则可以通过以下方式将其删除:
df.columns = df.columns.get_level_values(1)
# 0 class grade name
# 0 B A 1
# 1 A D 2