이 형식의 데이터가있는 txt 파일이 있습니다. 처음 3 줄은 계속 반복됩니다.
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 |
+-------+-----+
내가 찾고있는 것이 아닙니다.
답변
이 솔루션에서는 텍스트 형식이 설명 된대로 가정하지만 다른 단어를 사용하여 새 줄의 시작을 나타내도록 텍스트 형식을 수정할 수 있습니다. 여기서는 새로운 줄이 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.
답변
팬더를 사용하여 파일을 읽고 데이터를 처리 할 수 있습니다. 이것을 사용할 수 있습니다 :
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
답변
충분한 답변이 있다는 것을 알고 있지만 사전을 사용하여 다른 방법을 사용하십시오.
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
다른 관점을 얻으려면.
답변
출력을 얻었을 때 이것이 문제를 처리하는 방법입니다.
먼저 열의 반복성을 기반으로 고유 색인을 작성하십시오.
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
함수를 사용하여 데이터 프레임을 피벗하는 데 사용합니다
df1 = pd.crosstab(df['idx'],df['0'],values=df['1'],aggfunc='first').reset_index(drop=True)
print(df1[['name','grade','class']])
0 name grade class
0 1 A B
1 2 D A
답변
당신이 할 수있는 일은 file
3 블록으로 텍스트 파일 을 읽고 중첩 된 목록을 작성하고 데이터 프레임에 넣는 것입니다.
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
솔루션 보다 더 많은 코드 줄을 만들지 만 내 경험상 더 적은 pandas
기능을 사용 하므로 오버 헤드 가 적기 때문에 더 효율적일 것 입니다.
참고 # 2 : 일반적으로 입력 데이터를 다른 형식 (예 : json
또는) 으로 저장하는 것이 좋습니다 csv
. 예를 들어 csv 파일의 경우 read_csvpandas
함수 를 사용하면 훨씬 쉽게 읽을 수 있습니다.
답변
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
답변
IMHO, 모든 현재 답변이 너무 복잡해 보입니다. 내가 할 일은 2 열을 읽은 다음 얻은 DataFrame 을 읽는 매개 변수 로 사용 '='
하는 것입니다.sep
pd.read_csv
pivot
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