วิธีทำตัวอย่างแพนด้าที่ทำซ้ำได้ดี


221

ต้องใช้เวลาพอสมควรในการดูทั้งสอง และ แท็กใน SO การแสดงผลที่ฉันได้รับคือpandasคำถามมีโอกาสน้อยที่จะมีข้อมูลที่ทำซ้ำได้ นี่คือบางสิ่งที่ชุมชน R ได้รับการสนับสนุนค่อนข้างดีและด้วยคำแนะนำเช่นนี้ผู้มาใหม่ก็สามารถได้รับความช่วยเหลือในการรวบรวมตัวอย่างเหล่านี้ ผู้ที่สามารถอ่านคำแนะนำเหล่านี้และกลับมาพร้อมข้อมูลที่ทำซ้ำได้มักจะมีโชคที่ดีกว่ามากในการตอบคำถามของพวกเขา

เราจะสร้างตัวอย่างที่ทำซ้ำได้ดีสำหรับpandasคำถามได้อย่างไร ดาต้าเฟรมง่าย ๆ สามารถรวมกันได้เช่น:

import pandas as pd
df = pd.DataFrame({'user': ['Bob', 'Jane', 'Alice'], 
                   'income': [40000, 50000, 42000]})

แต่ชุดข้อมูลตัวอย่างจำนวนมากต้องการโครงสร้างที่ซับซ้อนมากขึ้นเช่น:

  • datetime ดัชนีหรือข้อมูล
  • ตัวแปรเด็ดขาดหลายตัว (มีexpand.grid()ฟังก์ชั่นเทียบเท่ากับ R ซึ่งสร้างชุดค่าผสมที่เป็นไปได้ทั้งหมดหรือไม่)
  • ข้อมูล MultiIndex หรือ Panel

สำหรับชุดข้อมูลที่ยากต่อการลอกเลียนแบบโดยใช้โค้ดสองสามบรรทัดจะมีค่าเทียบเท่ากับ R's dput()ที่อนุญาตให้คุณสร้างโค้ดที่คัดลอกได้เพื่อสร้างโครงสร้างข้อมูลใหม่หรือไม่


8
หากคุณคัดลอกผลลัพธ์ของการพิมพ์ผู้ตอบคำถามส่วนใหญ่สามารถใช้ read_clipboard () ... ยกเว้น MultiIndex: s บอกว่า dict เป็นการเพิ่มที่ดี
Andy Hayden

8
นอกจากสิ่งที่แอนดี้พูดฉันคิดว่าการคัดลอกวางdf.head(N).to_dict()ซึ่งNมีจำนวนพอสมควรเป็นวิธีที่ดีในการไป โบนัส +1 สำหรับการเพิ่มตัวแบ่งบรรทัดสวยไปยังเอาต์พุต สำหรับการประทับเวลาคุณจะต้องเพิ่มfrom pandas import Timestampที่ด้านบนสุดของรหัส
พอลเอช

คำตอบ:


323

หมายเหตุ: ความคิดที่นี่มีทั่วไปสวยสำหรับกองมากเกินจริงคำถาม

คำเตือน: การเขียนคำถามที่ดีคือยาก

ดี:

  • อย่ารวม DataFrame ขนาดเล็ก * ตัวอย่างเช่นเป็นรหัสที่รันได้:

    In [1]: df = pd.DataFrame([[1, 2], [1, 3], [4, 6]], columns=['A', 'B'])

    หรือทำให้เป็น "คัดลอกและวางได้" โดยใช้pd.read_clipboard(sep='\s\s+')คุณสามารถจัดรูปแบบข้อความสำหรับไฮไลต์ Stack Overflow และใช้Ctrl+ K(หรือเพิ่มช่องว่างสี่ช่องลงในแต่ละบรรทัด) หรือวางเครื่องหมายทวิภาคสามตัวด้านบนและด้านล่างรหัสของคุณด้วยโค้ดของคุณ

    In [2]: df
    Out[2]: 
       A  B
    0  1  2
    1  1  3
    2  4  6

    ทดสอบpd.read_clipboard(sep='\s\s+')ด้วยตัวเอง

    * ผมหมายถึงขนาดเล็กส่วนใหญ่ของตัวอย่าง DataFrames อาจจะน้อยกว่า 6 แถวอ้างจำเป็นและฉันเดิมพันที่ฉันสามารถทำมันได้ใน 5 แถว คุณสามารถทำซ้ำข้อผิดพลาดด้วยdf = df.head()ถ้าไม่ทำเล่น ๆ เพื่อดูว่าคุณสามารถสร้าง DataFrame ขนาดเล็กซึ่งแสดงปัญหาที่คุณเผชิญอยู่หรือไม่

    * กฎทุกคนมีข้อยกเว้นที่เห็นได้ชัดหนึ่งสำหรับปัญหาประสิทธิภาพการทำงาน ( ซึ่งในกรณีนี้แน่นอนใช้ timeit% และอาจ% prun ) ที่คุณควรสร้าง (พิจารณาใช้ np.random.seed df = pd.DataFrame(np.random.randn(100000000, 10))เพื่อให้เรามีกรอบเดียวกันแน่นอน): กล่าวว่า "ทำให้รหัสนี้เร็วสำหรับฉัน" ไม่ได้อยู่ในหัวข้อสำหรับเว็บไซต์ ...

  • เขียนผลลัพธ์ที่คุณต้องการ (คล้ายกับด้านบน)

    In [3]: iwantthis
    Out[3]: 
       A  B
    0  1  5
    1  4  6

    อธิบายว่าตัวเลขมาจากไหน: 5 คือผลรวมของคอลัมน์ B สำหรับแถวที่ A คือ 1

  • แสดงรหัสที่คุณได้ลอง:

    In [4]: df.groupby('A').sum()
    Out[4]: 
       B
    A   
    1  5
    4  6

    แต่พูดในสิ่งที่ไม่ถูกต้อง: คอลัมน์ A อยู่ในดัชนีแทนที่จะเป็นคอลัมน์

  • แสดงให้เห็นว่าคุณได้ทำวิจัยแล้ว ( ค้นหาเอกสาร , ค้นหา StackOverflow ), ให้ข้อมูลสรุป:

    docstring สำหรับผลรวมระบุเพียง "คำนวณผลรวมของค่ากลุ่ม"

    เอกสาร GroupByไม่ให้ตัวอย่างใด ๆ นี้

    นอกเหนือ: df.groupby('A', as_index=False).sum()คำตอบที่นี่คือการใช้งาน

  • หากเกี่ยวข้องกับคุณที่มีคอลัมน์เวลาประทับเช่นคุณกำลังสุ่มใหม่หรือบางสิ่งบางอย่างให้ระบุอย่างชัดเจนและนำpd.to_datetimeไปใช้กับพวกเขาเพื่อวัดผลที่ดี **

    df['date'] = pd.to_datetime(df['date']) # this column ought to be date..

    ** บางครั้งนี่คือปัญหาของตัวเอง: พวกเขาเป็นสตริง

เลว:

  • ไม่รวม MultiIndex ซึ่งเราไม่สามารถคัดลอกและวางได้ (ดูด้านบน) นี่เป็นความคับข้องใจกับการแสดงผลเริ่มต้นของแพนด้า แต่น่ารำคาญอย่างไรก็ตาม:

    In [11]: df
    Out[11]:
         C
    A B   
    1 2  3
      2  6

    วิธีที่ถูกต้องคือการรวม DataFrame สามัญด้วยการset_indexโทร:

    In [12]: df = pd.DataFrame([[1, 2, 3], [1, 2, 6]], columns=['A', 'B', 'C']).set_index(['A', 'B'])
    
    In [13]: df
    Out[13]: 
         C
    A B   
    1 2  3
      2  6
  • ให้ข้อมูลเชิงลึกเกี่ยวกับสิ่งที่เป็นเมื่อให้ผลลัพธ์ที่คุณต้องการ:

       B
    A   
    1  1
    5  0

    มีความเจาะจงเกี่ยวกับวิธีที่คุณได้รับตัวเลข (คืออะไร) ... ตรวจสอบอีกครั้งว่าถูกต้อง

  • หากรหัสของคุณมีข้อผิดพลาดให้รวมการติดตามสแต็กทั้งหมด (สามารถแก้ไขได้ในภายหลังหากเสียงดังเกินไป) แสดงหมายเลขบรรทัด (และบรรทัดที่สอดคล้องกันของรหัสของคุณซึ่งมันกำลังต่อต้าน)

น่าเกลียด:

  • อย่าลิงก์ไปยัง csv ที่เราไม่สามารถเข้าถึงได้ (อย่าลิงก์ไปยังแหล่งข้อมูลภายนอกเลย ... )

    df = pd.read_csv('my_secret_file.csv')  # ideally with lots of parsing options

    ข้อมูลส่วนใหญ่เป็นกรรมสิทธิ์ที่เราได้รับ: ทำข้อมูลที่คล้ายกันและดูว่าคุณสามารถทำให้เกิดปัญหาซ้ำ (มีขนาดเล็ก)

  • อย่าอธิบายสถานการณ์อย่างคลุมเครือในคำเช่นคุณมี DataFrame ซึ่งเป็น "ใหญ่" พูดถึงชื่อคอลัมน์บางส่วนในการผ่าน (โปรดอย่าพูดถึง dtypes ของพวกเขา) ลองดูรายละเอียดมากมายเกี่ยวกับสิ่งที่ไม่มีความหมายอย่างสมบูรณ์โดยไม่ต้องมองบริบทที่แท้จริง สันนิษฐานว่าไม่มีใครแม้แต่จะอ่านจนจบย่อหน้านี้

    บทความไม่ดีง่ายขึ้นด้วยตัวอย่างเล็ก ๆ

  • อย่ารวมสายข้อมูลที่ยาวกว่า 100 (100+ ??) ที่จะนำไปสู่คำถามที่แท้จริงของคุณ

    โปรดเราเห็นสิ่งนี้มากพอในงานประจำวันของเรา เราต้องการที่จะช่วยเหลือ แต่ไม่ได้เช่นนี้ ...
    ตัดบทนำและเพียงแสดง DataFrames ที่เกี่ยวข้อง (หรือเวอร์ชันเล็ก ๆ ของพวกเขา) ในขั้นตอนที่ทำให้คุณเดือดร้อน

อย่างไรก็ตามมีความสนุกสนานในการเรียนรู้ Python, NumPy และ Pandas!


30
+1 สำหรับส่วนpd.read_clipboard(sep='\s\s+')ปลาย เมื่อฉันโพสต์คำถาม SO ที่ต้องการดาต้าเฟรมที่แชร์เป็นพิเศษ แต่ง่าย ๆเช่นที่ฉันสร้างไว้ใน excel ให้คัดลอกไปยังคลิปบอร์ดของฉันจากนั้นสั่งให้โซเซอร์ทำเช่นเดียวกัน ประหยัดเวลาได้มาก!
zelusp

1
pd.read_clipboard(sep='\s\s+')ข้อเสนอแนะดูเหมือนจะไม่ทำงานหากคุณกำลังใช้งูหลามบนเซิร์ฟเวอร์ระยะไกลซึ่งเป็นที่มากของชุดข้อมูลขนาดใหญ่อาศัยอยู่
user5359531

1
ทำไมpd.read_clipboard(sep='\s\s+')และไม่ง่ายกว่าpd.read_clipboard()(พร้อมค่าเริ่มต้น‘s+’) อันดับแรกต้องมีอักขระช่องว่างอย่างน้อย 2 ตัวซึ่งอาจทำให้เกิดปัญหาหากมีเพียง 1 ตัวเท่านั้น (เช่นดูในคำตอบของ @JohnE )
MarianD

3
@MarianD เหตุผลที่ \ s \ s + ได้รับความนิยมอย่างมากคือมักจะมีหนึ่งตัวอย่างในชื่อคอลัมน์ แต่มีหลายรายการที่หาได้ยากยิ่งขึ้น เนื่องจากนี่เป็นเพียงชุดของเล่น / ชุดข้อมูลขนาดเล็กมันมีประสิทธิภาพมาก / ส่วนใหญ่คดี หมายเหตุ: แท็บที่คั่นจะเป็นเรื่องราวที่แตกต่างแม้ว่า stackoverflow จะแทนที่แท็บด้วยช่องว่าง แต่ถ้าคุณมี tsv ให้ใช้ \ t
Andy Hayden

3
ฮึฉันมักจะใช้pd.read_clipboard()เมื่อเป็นที่ว่างฉันทำpd.read_clipboard(sep='\s+{2,}', engine='python'): P
ส่งต่อ

72

วิธีสร้างชุดข้อมูลตัวอย่าง

นี่คือเพื่อขยายคำตอบของ @ AndyHayden เป็นหลักโดยการให้ตัวอย่างของวิธีที่คุณสามารถสร้างตัวอย่างข้อมูล Pandas และ (โดยเฉพาะ) ผู้ใช้จำนวนมากให้เครื่องมือต่าง ๆ เช่นนี้ซึ่งโดยทั่วไปคุณสามารถสร้างโทรสารที่เหมาะสมของชุดข้อมูลจริง ๆ ด้วยรหัสเพียงไม่กี่บรรทัด

หลังจากนำเข้าจำนวนมากและหมีแพนด้าให้แน่ใจว่าได้ให้เมล็ดพันธุ์แบบสุ่มถ้าคุณต้องการให้คนสามารถทำซ้ำข้อมูลและผลลัพธ์ของคุณ

import numpy as np
import pandas as pd

np.random.seed(123)

ตัวอย่างอ่างล้างจาน

นี่คือตัวอย่างที่แสดงความหลากหลายของสิ่งที่คุณสามารถทำได้ ตัวอย่างข้อมูลที่เป็นประโยชน์ทุกประเภทสามารถสร้างได้จากเซ็ตย่อยของสิ่งนี้:

df = pd.DataFrame({ 

    # some ways to create random data
    'a':np.random.randn(6),
    'b':np.random.choice( [5,7,np.nan], 6),
    'c':np.random.choice( ['panda','python','shark'], 6),

    # some ways to create systematic groups for indexing or groupby
    # this is similar to r's expand.grid(), see note 2 below
    'd':np.repeat( range(3), 2 ),
    'e':np.tile(   range(2), 3 ),

    # a date range and set of random dates
    'f':pd.date_range('1/1/2011', periods=6, freq='D'),
    'g':np.random.choice( pd.date_range('1/1/2011', periods=365, 
                          freq='D'), 6, replace=False) 
    })

สิ่งนี้ผลิต:

          a   b       c  d  e          f          g
0 -1.085631 NaN   panda  0  0 2011-01-01 2011-08-12
1  0.997345   7   shark  0  1 2011-01-02 2011-11-10
2  0.282978   5   panda  1  0 2011-01-03 2011-10-30
3 -1.506295   7  python  1  1 2011-01-04 2011-09-07
4 -0.578600 NaN   shark  2  0 2011-01-05 2011-02-27
5  1.651437   7  python  2  1 2011-01-06 2011-02-03

หมายเหตุบางส่วน:

  1. np.repeatและnp.tile(คอลัมน์dและe) มีประโยชน์มากสำหรับการสร้างกลุ่มและดัชนีในแบบปกติ สำหรับ 2 คอลัมน์สิ่งนี้สามารถใช้เพื่อทำซ้ำ r ได้อย่างง่ายดายexpand.grid()แต่ยังมีความยืดหยุ่นมากกว่าในการให้เซตย่อยของการเรียงสับเปลี่ยนทั้งหมด อย่างไรก็ตามสำหรับคอลัมน์ตั้งแต่ 3 คอลัมน์ขึ้นไปไวยากรณ์จะเปลี่ยนไปอย่างรวดเร็ว
  2. สำหรับแทนโดยตรงมากขึ้นสำหรับอาร์เอสexpand.grid()ดูitertoolsวิธีการแก้ปัญหาในหมีแพนด้าตำราหรือnp.meshgridวิธีการแก้ปัญหาที่แสดงที่นี่ สิ่งเหล่านี้จะอนุญาตให้มีมิติข้อมูลจำนวนเท่าใดก็ได้
  3. np.random.choiceคุณสามารถทำได้ไม่น้อยด้วย ตัวอย่างเช่นในคอลัมน์gเรามีการสุ่มเลือก 6 วันจาก 2011 นอกจากนี้โดยการตั้งค่าreplace=Falseเราสามารถมั่นใจได้ว่าวันที่เหล่านี้จะไม่ซ้ำกัน - มีประโยชน์มากถ้าเราต้องการที่จะใช้สิ่งนี้เป็นดัชนีที่มีค่าที่ไม่ซ้ำกัน

ข้อมูลตลาดหุ้นปลอม

นอกเหนือจากการรับเซตย่อยของโค้ดข้างต้นแล้วคุณยังสามารถรวมเทคนิคต่าง ๆ เพื่อทำอะไรก็ได้ ตัวอย่างเช่นต่อไปนี้เป็นตัวอย่างสั้น ๆ ที่รวมnp.tileและdate_rangeสร้างข้อมูลทิกเกอร์ตัวอย่างสำหรับ 4 หุ้นที่ครอบคลุมวันเดียวกัน

stocks = pd.DataFrame({ 
    'ticker':np.repeat( ['aapl','goog','yhoo','msft'], 25 ),
    'date':np.tile( pd.date_range('1/1/2011', periods=25, freq='D'), 4 ),
    'price':(np.random.randn(100).cumsum() + 10) })

ขณะนี้เรามีชุดข้อมูลตัวอย่างที่มี 100 บรรทัด (25 วันต่อหนึ่งทิกเกอร์) แต่เราใช้เพียง 4 บรรทัดในการทำมันทำให้ทุกคนสามารถทำซ้ำได้ง่ายโดยไม่ต้องคัดลอกและวางโค้ด 100 บรรทัด จากนั้นคุณสามารถแสดงชุดย่อยของข้อมูลหากช่วยอธิบายคำถามของคุณ:

>>> stocks.head(5)

        date      price ticker
0 2011-01-01   9.497412   aapl
1 2011-01-02  10.261908   aapl
2 2011-01-03   9.438538   aapl
3 2011-01-04   9.515958   aapl
4 2011-01-05   7.554070   aapl

>>> stocks.groupby('ticker').head(2)

         date      price ticker
0  2011-01-01   9.497412   aapl
1  2011-01-02  10.261908   aapl
25 2011-01-01   8.277772   goog
26 2011-01-02   7.714916   goog
50 2011-01-01   5.613023   yhoo
51 2011-01-02   6.397686   yhoo
75 2011-01-01  11.736584   msft
76 2011-01-02  11.944519   msft

2
คำตอบที่ดี หลังจากเขียนคำถามนี้ฉันจริง ๆ แล้วเขียนสั้น ๆ ง่าย ๆ การใช้งานexpand.grid()ที่รวมอยู่ในตำราของแพนด้าคุณสามารถรวมไว้ในคำตอบของคุณเช่นกัน คำตอบของคุณแสดงวิธีสร้างชุดข้อมูลที่ซับซ้อนกว่าexpand_grid()ฟังก์ชั่นของฉันที่สามารถจัดการได้ซึ่งยอดเยี่ยมมาก
Marius

46

ไดอารี่ของผู้ตอบคำถาม

คำแนะนำที่ดีที่สุดของฉันสำหรับการถามคำถามคือการเล่นจิตวิทยาของคนที่ตอบคำถาม เป็นหนึ่งในคนเหล่านั้นฉันสามารถให้ข้อมูลเชิงลึกเกี่ยวกับสาเหตุที่ฉันตอบคำถามบางอย่างและทำไมฉันไม่ตอบคนอื่น

แรงจูงใจ

ฉันมีแรงจูงใจที่จะตอบคำถามด้วยเหตุผลหลายประการ

  1. Stackoverflow.com เป็นทรัพยากรที่มีค่ามากสำหรับฉัน ฉันต้องการคืน
  2. ในความพยายามของฉันที่จะคืนเงินฉันพบว่าไซต์นี้เป็นทรัพยากรที่ทรงพลังยิ่งกว่าเมื่อก่อน ตอบคำถามเป็นประสบการณ์การเรียนรู้สำหรับฉันและฉันชอบที่จะเรียนรู้ อ่านคำตอบนี้และแสดงความคิดเห็นจากสัตว์แพทย์อีก การมีปฏิสัมพันธ์แบบนี้ทำให้ฉันมีความสุข
  3. ฉันชอบคะแนน!
  4. ดู # 3
  5. ฉันชอบปัญหาที่น่าสนใจ

ความตั้งใจที่บริสุทธิ์ที่สุดของฉันนั้นยอดเยี่ยมมากและทั้งหมด แต่ฉันได้รับความพึงพอใจอย่างนั้นถ้าฉันตอบคำถาม 1 ข้อหรือข้อ 30 สิ่งที่ผลักดันทางเลือกของฉันสำหรับคำถามที่จะตอบมีองค์ประกอบที่ใหญ่ที่สุดของการเพิ่มจุด

ฉันจะใช้เวลากับปัญหาที่น่าสนใจด้วย แต่ก็มีอยู่ไม่มากนักและไม่ช่วยผู้ถามที่ต้องการคำตอบสำหรับคำถามที่ไม่น่าสนใจ ทางออกที่ดีที่สุดของคุณเพื่อให้ฉันตอบคำถามก็คือตอบคำถามนั้นบนแผ่นเสียงที่สุกแล้วสำหรับฉันที่จะตอบคำถามด้วยความพยายามน้อยที่สุดเท่าที่จะทำได้ หากฉันดูคำถามสองข้อและมีรหัสฉันสามารถคัดลอกวางเพื่อสร้างตัวแปรทั้งหมดที่ฉันต้องการ ... ฉันกำลังทำอย่างนั้น! ฉันจะกลับไปหาคนอื่นถ้าฉันมีเวลาบางที

คำแนะนำหลัก

ทำให้เป็นเรื่องง่ายสำหรับผู้ที่ตอบคำถาม

  • ระบุรหัสที่สร้างตัวแปรที่จำเป็น
  • ย่อเล็กสุดรหัสนั้น หากสายตาของฉันจ้องมองไปที่ฉันดูที่โพสต์ฉันจะไปที่คำถามต่อไปหรือกลับไปที่สิ่งที่ฉันทำ
  • คิดเกี่ยวกับสิ่งที่คุณถามและเฉพาะเจาะจง เราต้องการที่จะเห็นสิ่งที่คุณทำเพราะภาษาธรรมชาติ (อังกฤษ) ไม่แน่นอนและสับสน ตัวอย่างโค้ดของสิ่งที่คุณพยายามช่วยแก้ไขความไม่สอดคล้องกันในคำอธิบายภาษาธรรมชาติ
  • โปรดแสดงสิ่งที่คุณคาดหวัง !!! ฉันต้องนั่งลงและลองสิ่งต่างๆ ฉันแทบไม่เคยรู้คำตอบของคำถามโดยไม่ลองทำ หากฉันไม่เห็นตัวอย่างของสิ่งที่คุณกำลังมองหาฉันอาจส่งต่อคำถามนี้เพราะฉันไม่อยากเดา

ชื่อเสียงของคุณเป็นมากกว่าแค่ชื่อเสียงของคุณ

ฉันชอบคะแนน (ฉันพูดถึงข้างบน) แต่ประเด็นเหล่านั้นไม่ใช่ชื่อเสียงของฉันจริงๆ ชื่อเสียงที่แท้จริงของฉันคือการรวมกันของสิ่งที่คนอื่นในเว็บไซต์คิดกับฉัน ฉันมุ่งมั่นที่จะเป็นธรรมและซื่อสัตย์และฉันหวังว่าคนอื่นจะเห็นว่า สิ่งที่มีความหมายสำหรับผู้ถามคือเราจำพฤติกรรมของผู้ถามได้ หากคุณไม่เลือกคำตอบและถอนคำตอบที่ดีฉันจำได้ หากคุณประพฤติตัวในแบบที่ฉันไม่ชอบหรือในแบบที่ฉันชอบฉันจำได้ นอกจากนี้ยังเล่นเป็นคำถามที่ฉันจะตอบ


อย่างไรก็ตามฉันอาจจะไปต่อ แต่ฉันจะขอสงวนไว้สำหรับทุกคนที่อ่านข้อความนี้


26

ความท้าทายหนึ่งในแง่มุมที่ท้าทายที่สุดในการตอบคำถาม SO คือเวลาที่ใช้ในการสร้างปัญหาขึ้นใหม่ (รวมถึงข้อมูล) คำถามที่ไม่มีวิธีการที่ชัดเจนในการสร้างข้อมูลมีโอกาสน้อยที่จะตอบ เนื่องจากคุณใช้เวลาในการเขียนคำถามและมีปัญหาที่คุณต้องการความช่วยเหลือคุณสามารถช่วยตัวเองได้อย่างง่ายดายด้วยการให้ข้อมูลที่ผู้อื่นสามารถใช้เพื่อช่วยแก้ปัญหาของคุณ

คำแนะนำจาก @Andy สำหรับการเขียนคำถาม Pandas ที่ดีนั้นเป็นจุดเริ่มต้นที่ดีเยี่ยม สำหรับข้อมูลเพิ่มเติมอ้างถึงวิธีถามและวิธีสร้างตัวอย่างที่น้อยที่สุดสมบูรณ์และตรวจสอบได้

โปรดระบุคำถามของคุณอย่างชัดเจนล่วงหน้า หลังจากสละเวลาในการเขียนคำถามของคุณและโค้ดตัวอย่างใด ๆ ลองอ่านและให้ 'บทสรุปผู้บริหาร' สำหรับผู้อ่านของคุณซึ่งสรุปปัญหาและระบุคำถามไว้อย่างชัดเจน

คำถามเดิม :

ฉันมีข้อมูลนี้ ...

ฉันต้องการทำสิ่งนี้ ...

ฉันต้องการให้ผลลัพธ์ของฉันมีลักษณะเช่นนี้ ...

อย่างไรก็ตามเมื่อฉันพยายามทำสิ่งนี้ฉันได้รับปัญหาต่อไปนี้ ...

ฉันพยายามค้นหาวิธีแก้ปัญหาด้วยการทำ [สิ่งนี้] และ [สิ่งนั้น]

ฉันจะแก้ไขได้อย่างไร

ขึ้นอยู่กับปริมาณของข้อมูลโค้ดตัวอย่างและสแต็คข้อผิดพลาดที่มีให้ผู้อ่านต้องไปไกลก่อนที่จะเข้าใจว่าปัญหาคืออะไร ลองทบทวนคำถามของคุณใหม่เพื่อให้คำถามนั้นอยู่ด้านบนสุดจากนั้นให้รายละเอียดที่จำเป็น

คำถามที่มีการแก้ไข :

Qustion: ฉันจะทำ [สิ่งนี้] ได้อย่างไร?

ฉันพยายามค้นหาวิธีแก้ปัญหาด้วยการทำ [สิ่งนี้] และ [สิ่งนั้น]

เมื่อฉันพยายามทำสิ่งนี้ฉันได้รับปัญหาต่อไปนี้ ...

ฉันต้องการให้ผลลัพธ์สุดท้ายของฉันมีลักษณะเช่นนี้ ...

นี่คือรหัสขั้นต่ำที่สามารถทำให้เกิดปัญหาของฉันได้ ...

และนี่คือวิธีการสร้างข้อมูลตัวอย่างของฉันใหม่: df = pd.DataFrame({'A': [...], 'B': [...], ...})

ให้ข้อมูลตัวอย่างถ้าจำเป็น !!!

บางครั้งเพียงแค่หัวหรือส่วนท้ายของ DataFrame เป็นสิ่งที่จำเป็น คุณยังสามารถใช้วิธีการที่เสนอโดย @JohnE เพื่อสร้างชุดข้อมูลขนาดใหญ่ที่คนอื่นสามารถทำซ้ำได้ ใช้ตัวอย่างของเขาเพื่อสร้าง DataFrame 100 แถวของราคาหุ้น:

stocks = pd.DataFrame({ 
    'ticker':np.repeat( ['aapl','goog','yhoo','msft'], 25 ),
    'date':np.tile( pd.date_range('1/1/2011', periods=25, freq='D'), 4 ),
    'price':(np.random.randn(100).cumsum() + 10) })

หากนี่เป็นข้อมูลจริงของคุณคุณอาจต้องการรวมส่วนหัวและ / หรือส่วนท้ายของ dataframe ดังต่อไปนี้ (อย่าลืมเปิดเผยชื่อที่ละเอียดอ่อนของข้อมูลที่สำคัญ):

>>> stocks.head(5).to_dict()
{'date': {0: Timestamp('2011-01-01 00:00:00'),
  1: Timestamp('2011-01-01 00:00:00'),
  2: Timestamp('2011-01-01 00:00:00'),
  3: Timestamp('2011-01-01 00:00:00'),
  4: Timestamp('2011-01-02 00:00:00')},
 'price': {0: 10.284260107718254,
  1: 11.930300761831457,
  2: 10.93741046217319,
  3: 10.884574289565609,
  4: 11.78005850418319},
 'ticker': {0: 'aapl', 1: 'aapl', 2: 'aapl', 3: 'aapl', 4: 'aapl'}}

>>> pd.concat([stocks.head(), stocks.tail()], ignore_index=True).to_dict()
{'date': {0: Timestamp('2011-01-01 00:00:00'),
  1: Timestamp('2011-01-01 00:00:00'),
  2: Timestamp('2011-01-01 00:00:00'),
  3: Timestamp('2011-01-01 00:00:00'),
  4: Timestamp('2011-01-02 00:00:00'),
  5: Timestamp('2011-01-24 00:00:00'),
  6: Timestamp('2011-01-25 00:00:00'),
  7: Timestamp('2011-01-25 00:00:00'),
  8: Timestamp('2011-01-25 00:00:00'),
  9: Timestamp('2011-01-25 00:00:00')},
 'price': {0: 10.284260107718254,
  1: 11.930300761831457,
  2: 10.93741046217319,
  3: 10.884574289565609,
  4: 11.78005850418319,
  5: 10.017209045035006,
  6: 10.57090128181566,
  7: 11.442792747870204,
  8: 11.592953372130493,
  9: 12.864146419530938},
 'ticker': {0: 'aapl',
  1: 'aapl',
  2: 'aapl',
  3: 'aapl',
  4: 'aapl',
  5: 'msft',
  6: 'msft',
  7: 'msft',
  8: 'msft',
  9: 'msft'}}

คุณอาจต้องการให้คำอธิบายของ DataFrame (ใช้เฉพาะคอลัมน์ที่เกี่ยวข้อง) ทำให้ผู้อื่นสามารถตรวจสอบประเภทข้อมูลของแต่ละคอลัมน์ได้ง่ายขึ้นและระบุข้อผิดพลาดทั่วไปอื่น ๆ (เช่นวันที่เป็นสตริงเทียบกับวันที่และเวลา 64 กับวัตถุ):

stocks.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 100 entries, 0 to 99
Data columns (total 3 columns):
date      100 non-null datetime64[ns]
price     100 non-null float64
ticker    100 non-null object
dtypes: datetime64[ns](1), float64(1), object(1)

หมายเหตุ: หาก DataFrame ของคุณมี MultiIndex:

หากคุณมี DataFrame multiindex to_dictก่อนอื่นคุณต้องตั้งค่าก่อนที่จะเรียก จากนั้นคุณต้องสร้างดัชนีใหม่โดยใช้set_index:

# MultiIndex example.  First create a MultiIndex DataFrame.
df = stocks.set_index(['date', 'ticker'])
>>> df
                       price
date       ticker           
2011-01-01 aapl    10.284260
           aapl    11.930301
           aapl    10.937410
           aapl    10.884574
2011-01-02 aapl    11.780059
...

# After resetting the index and passing the DataFrame to `to_dict`, make sure to use 
# `set_index` to restore the original MultiIndex.  This DataFrame can then be restored.

d = df.reset_index().to_dict()
df_new = pd.DataFrame(d).set_index(['date', 'ticker'])
>>> df_new.head()
                       price
date       ticker           
2011-01-01 aapl    10.284260
           aapl    11.930301
           aapl    10.937410
           aapl    10.884574
2011-01-02 aapl    11.780059

12

นี่คือเวอร์ชันของฉันdput- เครื่องมือมาตรฐาน R เพื่อสร้างรายงานที่ทำซ้ำได้ - สำหรับ Pandas DataFrames มันอาจจะล้มเหลวสำหรับเฟรมที่ซับซ้อนมากขึ้น แต่ดูเหมือนว่าจะทำงานในกรณีง่าย ๆ :

import pandas as pd
def dput (x):
    if isinstance(x,pd.Series):
        return "pd.Series(%s,dtype='%s',index=pd.%s)" % (list(x),x.dtype,x.index)
    if isinstance(x,pd.DataFrame):
        return "pd.DataFrame({" + ", ".join([
            "'%s': %s" % (c,dput(x[c])) for c in x.columns]) + (
                "}, index=pd.%s)" % (x.index))
    raise NotImplementedError("dput",type(x),x)

ตอนนี้

df = pd.DataFrame({'a':[1,2,3,4,2,1,3,1]})
assert df.equals(eval(dput(df)))
du = pd.get_dummies(df.a,"foo")
assert du.equals(eval(dput(du)))
di = df
di.index = list('abcdefgh')
assert di.equals(eval(dput(di)))

โปรดทราบว่าสิ่งนี้สร้างผลลัพธ์ verbose มากกว่าDataFrame.to_dictเช่น

pd.DataFrame({
  'foo_1':pd.Series([1, 0, 0, 0, 0, 1, 0, 1],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)),
  'foo_2':pd.Series([0, 1, 0, 0, 1, 0, 0, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)),
  'foo_3':pd.Series([0, 0, 1, 0, 0, 0, 1, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)),
  'foo_4':pd.Series([0, 0, 0, 1, 0, 0, 0, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1))},
  index=pd.RangeIndex(start=0, stop=8, step=1))

VS

{'foo_1': {0: 1, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1, 6: 0, 7: 1}, 
 'foo_2': {0: 0, 1: 1, 2: 0, 3: 0, 4: 1, 5: 0, 6: 0, 7: 0}, 
 'foo_3': {0: 0, 1: 0, 2: 1, 3: 0, 4: 0, 5: 0, 6: 1, 7: 0}, 
 'foo_4': {0: 0, 1: 0, 2: 0, 3: 1, 4: 0, 5: 0, 6: 0, 7: 0}}

สำหรับduด้านบน แต่จะรักษาประเภทคอลัมน์ไว้ เช่นในกรณีทดสอบข้างต้น

du.equals(pd.DataFrame(du.to_dict()))
==> False

เพราะdu.dtypesเป็นuint8และเป็นpd.DataFrame(du.to_dict()).dtypesint64


เป็นที่ชัดเจนถึงแม้ว่าฉันยอมรับว่าฉันไม่เห็นว่าทำไมฉันต้องการใช้มากกว่าto_dict
พอลเอช

2
เพราะมันรักษาประเภทคอลัมน์ โดยเฉพาะอย่างยิ่ง, du.equals(eval(dput(df))).
sds
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.