python - डेटाफ़्रेम में बार-बार "कुंजी=मान" जोड़े की फ़ाइल पढ़ें




pandas (5)

मेरे पास इस प्रारूप में डेटा के साथ एक 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   |
+-------+-----+

नहीं वास्तव में मैं क्या देख रहा हूँ।


IMHO, सभी वर्तमान उत्तर बहुत जटिल दिखते हैं। मैं क्या करूँगा, 2 कॉलम पढ़ने के लिए read_csv sep पैरामीटर के रूप में '=' का उपयोग करना है, और फिर प्राप्त डेटाफ़्रेम को 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

आप पायथन के शब्दकोश मॉड्यूल और पंडों का उपयोग करके उस आउटपुट को उत्पन्न कर सकते हैं।

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)

यह दृष्टिकोण सबसे कुशल नहीं हो सकता है लेकिन यह पंडों के किसी भी उन्नत कार्य का उपयोग नहीं करता है। आशा करता हूँ की ये काम करेगा।

उत्पादन:

    name    grade   class
0      1        A       B
1      2        D       A

आप फ़ाइल को पढ़ने और डेटा को संसाधित करने के लिए पांडा का उपयोग कर सकते हैं। आप इसका उपयोग कर सकते हैं:

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

जैसा कि आपको एक आउटपुट मिला है कि मैं इस समस्या से कैसे निपटूंगा:

सबसे पहले स्तंभों की पुनरावृत्ति के आधार पर एक अद्वितीय सूचकांक बनाएं,

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

यह समाधान पाठ प्रारूप को मानता है जैसा आपने वर्णित किया है, लेकिन आप एक नई पंक्ति की शुरुआत को निरूपित करने के लिए एक अलग शब्द का उपयोग करने के लिए इसे संशोधित कर सकते हैं। यहां, हम मानते हैं कि एक नई लाइन 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.




pandas