নেস্টেড অভিধানে আইটেমগুলি থেকে পান্ডাস ডেটা ফ্রেম তৈরি করুন Const


90

মনে করুন কাঠামোর সাথে আমার নেস্টেড ডিকশনারি 'ইউজার_ডিক্ট' রয়েছে:

  • স্তর 1: ইউজারআইডি (দীর্ঘ পূর্ণসংখ্যা)
  • স্তর 2: বিভাগ (স্ট্রিং)
  • স্তর 3: বিবিধ বৈশিষ্ট্য (ভাসমান, ints, ইত্যাদি।)

উদাহরণস্বরূপ, এই অভিধানের একটি এন্ট্রি হবে:

user_dict[12] = {
    "Category 1": {"att_1": 1, 
                   "att_2": "whatever"},
    "Category 2": {"att_1": 23, 
                   "att_2": "another"}}

প্রতিটি আইটেমের user_dictএকই কাঠামো থাকে এবং user_dictবৃহত সংখ্যক আইটেম থাকে যা বৈশিষ্ট্যগুলি থেকে সিরিজটি তৈরি করে আমি একটি পান্ডাস ডেটা ফ্রেমে ফিড করতে চাই। এক্ষেত্রে একটি শ্রেণিবিন্যাস সূচক কার্যকর হবে।

বিশেষত, আমার প্রশ্নটি এই যে ডেটাফ্রেম নির্মাতাকে বুঝতে সাহায্য করার কোনও উপায় আছে কি যে অভিধানটিতে "স্তর 3" এর মানগুলি থেকে সিরিজটি তৈরি করা উচিত?

আমি যদি এরকম কিছু চেষ্টা করি:

df = pandas.DataFrame(users_summary)

"স্তর 1" (ইউজারআইডি) এর আইটেমগুলি কলাম হিসাবে নেওয়া হয়, যা আমি অর্জন করতে চাই তার বিপরীত (ইউজারআইডিকে সূচক হিসাবে থাকতে হবে)।

আমি জানি আমি অভিধানের এন্ট্রিগুলিতে পুনরাবৃত্তি করার পরে সিরিজটি তৈরি করতে পারতাম, তবে যদি আরও সরাসরি কোনও উপায় থাকে তবে এটি খুব কার্যকর হবে। অনুরূপ একটি প্রশ্ন জিজ্ঞাসা করবে যে কোনও ফাইলে তালিকাভুক্ত জেসন অবজেক্ট থেকে প্যান্ডাস ডেটাফ্রেম তৈরি করা সম্ভব কিনা?


সহজ বিকল্পগুলির জন্য এই উত্তরটি দেখুন ।
সিএস 95

উত্তর:


138

একটি পান্ডাস মাল্টিআইএনডেক্সে টিপলগুলির একটি তালিকা রয়েছে। সুতরাং সবচেয়ে প্রাকৃতিক পদ্ধতির আপনার ইনপুট ডিক পুনরায় আকার দেওয়া হবে যাতে এর কীগুলি আপনার প্রয়োজনীয় মাল্টি-ইনডেক্স মানগুলির সাথে মিলিয়ে দ্বিগুণ হয়। তারপর আপনি শুধু ব্যবহার করে আপনার dataframe গঠন করা যেতে পারে pd.DataFrame.from_dict, বিকল্প ব্যবহার করে orient='index':

user_dict = {12: {'Category 1': {'att_1': 1, 'att_2': 'whatever'},
                  'Category 2': {'att_1': 23, 'att_2': 'another'}},
             15: {'Category 1': {'att_1': 10, 'att_2': 'foo'},
                  'Category 2': {'att_1': 30, 'att_2': 'bar'}}}

pd.DataFrame.from_dict({(i,j): user_dict[i][j] 
                           for i in user_dict.keys() 
                           for j in user_dict[i].keys()},
                       orient='index')


               att_1     att_2
12 Category 1      1  whatever
   Category 2     23   another
15 Category 1     10       foo
   Category 2     30       bar

বিকল্প পদ্ধতির অংশটি হ'ল উপাদান ডেটাফ্রেমগুলিকে একত্রিত করে আপনার ডেটা ফ্রেম তৈরি করা হবে:

user_ids = []
frames = []

for user_id, d in user_dict.iteritems():
    user_ids.append(user_id)
    frames.append(pd.DataFrame.from_dict(d, orient='index'))

pd.concat(frames, keys=user_ids)

               att_1     att_2
12 Category 1      1  whatever
   Category 2     23   another
15 Category 1     10       foo
   Category 2     30       bar

11
ইচ্ছামত গভীরতা র‌্যাগড তালিকাগুলি নিয়ে কাজ করার জন্য কি সাধারণীকরণের কোনও যুক্তিসঙ্গত উপায় আছে? উদাহরণস্বরূপ একটি স্বেচ্ছাসেবী গভীরতার তালিকাগুলি, যেখানে কিছু শাখা অন্যদের চেয়ে সংক্ষিপ্ত হতে পারে এবং সংক্ষিপ্ত শাখাগুলি শেষ না পৌঁছলে কোনও কিছুই বা ন্যান ব্যবহার করা হয় না?
nnot101

4
আপনি কি পান্ডাস জসন সমর্থন (আইও সরঞ্জামসমূহ) এবং স্বাভাবিককরণের দিকে নজর রেখেছেন? pandas.pydata.org/pandas-docs/dev/io.html# সাধারণকরণ
ওয়াটার ওভারমায়ার

4
আমার জন্য, প্রথম পদ্ধতিটি টিপলস সহ একক সূচক সহ একটি ডেটা ফ্রেম তৈরি করেছে। দ্বিতীয় পদ্ধতিটি পছন্দসই / প্রত্যাশার মতো কাজ করেছিল!
আর্টুরম্প

এই নতুন কলামগুলির নাম কীভাবে রাখবেন সে সম্পর্কে কোনও টিপস? উদাহরণস্বরূপ, যদি আমি এই সংখ্যাগুলি 12 এবং 15 কলামের 'আইডি' তে রাখতে চাই।
চেরেমুশকিন

4
@ চেরিমশকিন 12 এবং 15 এখন 'আইডি' সারিতে রয়েছে, আপনি ট্রান্সপোজ ( pandas.pydata.org/pandas-docs/stable/references/api/… ) তারা 'আইডি' কলামে রয়েছে। আপনি আনস্ট্যাকও করতে পারেন ( pandas.pydata.org/pandas-docs/stable/references/api/… ) এটি আপনার সত্যিকারের প্রয়োজনের উপর নির্ভর করে।
ওয়াউটার ওভারমিয়ার

31

pd.concatএকটি অভিধান গ্রহণ করে। এটি মনে রেখে, সাব-ফ্রেমগুলির অভিধান ম্যাপিং কী তৈরির জন্য অভিধান বোঝার সাহায্যে সরলতা এবং পারফরম্যান্সের ক্ষেত্রে বর্তমানে স্বীকৃত উত্তরের উপর উন্নতি করা সম্ভব ।

pd.concat({k: pd.DataFrame(v).T for k, v in user_dict.items()}, axis=0)

বা,

pd.concat({
        k: pd.DataFrame.from_dict(v, 'index') for k, v in user_dict.items()
    }, 
    axis=0)

              att_1     att_2
12 Category 1     1  whatever
   Category 2    23   another
15 Category 1    10       foo
   Category 2    30       bar

4
উজ্জ্বল! আরও অনেক ভাল :)
pg2455

4
আপনার যদি আরও একটি অভ্যন্তরীণ বিভাগ থাকে তবে আপনি এটি কীভাবে করবেন? যেমন 12:{cat1:{cat11:{att1:val1,att2:val2}}}। অন্য কথায়: কেউ কীভাবে একটি অপ্রাসঙ্গিক সংখ্যার বিভাগের সমাধানকে সাধারণীকরণ করবেন?
লুকাস আইমারেটো

4
@ লুকাসাইমারেট্টো সাধারণত নির্বিচারে নেস্টেড কাঠামো দিয়ে সমতল করা যায় json_normalize। আমার আরও একটি উত্তর আছে যা দেখায় যে এটি কীভাবে কাজ করে।
cs95

4
vউদাহরণস্বরূপ যদি একটি একক পূর্ণসংখ্যা হয় তবে কাজ করে না । আপনি কি এই ক্ষেত্রে একটি বিকল্প জানেন?
sk

11

সুতরাং আমি অভিধানের মাধ্যমে পুনরাবৃত্তি করার জন্য লুপের জন্যও ব্যবহার করতাম, তবে একটি জিনিস আমি খুঁজে পেয়েছি যে খুব দ্রুত কাজ করে তা হ'ল একটি প্যানেল এবং তারপরে একটি ডেটাফ্রেমে রূপান্তর করা। বলুন আপনার একটি অভিধান আছে d

import pandas as pd
d
{'RAY Index': {datetime.date(2014, 11, 3): {'PX_LAST': 1199.46,
'PX_OPEN': 1200.14},
datetime.date(2014, 11, 4): {'PX_LAST': 1195.323, 'PX_OPEN': 1197.69},
datetime.date(2014, 11, 5): {'PX_LAST': 1200.936, 'PX_OPEN': 1195.32},
datetime.date(2014, 11, 6): {'PX_LAST': 1206.061, 'PX_OPEN': 1200.62}},
'SPX Index': {datetime.date(2014, 11, 3): {'PX_LAST': 2017.81,
'PX_OPEN': 2018.21},
datetime.date(2014, 11, 4): {'PX_LAST': 2012.1, 'PX_OPEN': 2015.81},
datetime.date(2014, 11, 5): {'PX_LAST': 2023.57, 'PX_OPEN': 2015.29},
datetime.date(2014, 11, 6): {'PX_LAST': 2031.21, 'PX_OPEN': 2023.33}}}

আদেশ

pd.Panel(d)
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 2 (major_axis) x 4 (minor_axis)
Items axis: RAY Index to SPX Index
Major_axis axis: PX_LAST to PX_OPEN
Minor_axis axis: 2014-11-03 to 2014-11-06

যেখানে পিডি.প্যানেল (ডি) [আইটেম] একটি ডেটাফ্রেম দেয়

pd.Panel(d)['SPX Index']
2014-11-03  2014-11-04  2014-11-05 2014-11-06
PX_LAST 2017.81 2012.10 2023.57 2031.21
PX_OPEN 2018.21 2015.81 2015.29 2023.33

এরপরে আপনি এটি ডেটা ফ্রেমে রূপান্তরিত করতে __ ফ্রেম () কমান্ডটি চাপতে পারেন। আমি রিসেট_ইন্ডেক্সটি পাশাপাশি প্রধান এবং ছোটখাটো অক্ষকে সূচক হিসাবে না রেখে কলামগুলিতে পরিণত করতে ব্যবহার করি।

pd.Panel(d).to_frame().reset_index()
major   minor      RAY Index    SPX Index
PX_LAST 2014-11-03  1199.460    2017.81
PX_LAST 2014-11-04  1195.323    2012.10
PX_LAST 2014-11-05  1200.936    2023.57
PX_LAST 2014-11-06  1206.061    2031.21
PX_OPEN 2014-11-03  1200.140    2018.21
PX_OPEN 2014-11-04  1197.690    2015.81
PX_OPEN 2014-11-05  1195.320    2015.29
PX_OPEN 2014-11-06  1200.620    2023.33

অবশেষে, ফ্রেমটি দেখতে আপনার পছন্দ মতো না হলে আপনি_ফ্রেমে কল করার আগে চেহারাটি পরিবর্তন করতে প্যানেলের ট্রান্সপোজ ফাংশনটি ব্যবহার করতে পারেন () এখানে ডকুমেন্টেশন দেখুন http://pandas.pydata.org/pandas-docs/dev/nerated /pandas.Panel.transpose.html

যেমন একটি উদাহরণ

pd.Panel(d).transpose(2,0,1).to_frame().reset_index()
major        minor  2014-11-03  2014-11-04  2014-11-05  2014-11-06
RAY Index   PX_LAST 1199.46    1195.323     1200.936    1206.061
RAY Index   PX_OPEN 1200.14    1197.690     1195.320    1200.620
SPX Index   PX_LAST 2017.81    2012.100     2023.570    2031.210
SPX Index   PX_OPEN 2018.21    2015.810     2015.290    2023.330

আশাকরি এটা সাহায্য করবে.


8
প্যানেলটি পান্ডাসের আরও সাম্প্রতিক সংস্করণগুলিতে অবহিত করা হয়েছে (লেখার সময় v0.23)।
সিএস 95

6

যদি কেউ মাল্টিইন্ডেক্স ছাড়াই "দীর্ঘ বিন্যাসে" (পাতার মানগুলির একই ধরণের থাকে) ডেটা ফ্রেম পেতে চায়, আপনি এটি করতে পারেন:

pd.DataFrame.from_records(
    [
        (level1, level2, level3, leaf)
        for level1, level2_dict in user_dict.items()
        for level2, level3_dict in level2_dict.items()
        for level3, leaf in level3_dict.items()
    ],
    columns=['UserId', 'Category', 'Attribute', 'value']
)

    UserId    Category Attribute     value
0       12  Category 1     att_1         1
1       12  Category 1     att_2  whatever
2       12  Category 2     att_1        23
3       12  Category 2     att_2   another
4       15  Category 1     att_1        10
5       15  Category 1     att_2       foo
6       15  Category 2     att_1        30
7       15  Category 2     att_2       bar

(আমি জানি যে আসল প্রশ্নটি সম্ভবত (আই।) স্তরের 1 এবং 2 এবং মাল্টিইন্ডেক্স হিসাবে স্তর 3 এবং কলাম হিসাবে স্তর II (2) ডিকের মানগুলির চেয়ে পুনরাবৃত্তির চেয়ে অন্যান্য উপায় সম্পর্কে জিজ্ঞাসা করতে পারে I তবে আমি আশা করি এই উত্তরটি এখনও প্রাসঙ্গিক এবং দরকারী (আই।): আমার মতো লোকদের যারা নেস্টেড ডিককে এই আকারে আনার জন্য কোনও উপায় অনুসন্ধান করার চেষ্টা করেছেন এবং গুগল কেবল এই প্রশ্নটি দেয় এবং (II।): কারণ অন্যান্য উত্তরগুলির সাথে কিছু পুনরাবৃত্তিও জড়িত এবং আমি এটি খুঁজে পাই নমনীয় এবং সহজেই পড়া সহজ; কর্মক্ষমতা সম্পর্কে নিশ্চিত না, যদিও।)


0

যাচাই করা উত্তরের উপর ভিত্তি করে তৈরি করা, আমার জন্য এটি সবচেয়ে ভাল কাজ করেছে:

ab = pd.concat({k: pd.DataFrame(v).T for k, v in data.items()}, axis=0)
ab.T
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.