मैं दो कॉलम (index_start
और index_end
) में संख्यात्मक मानों के आधार पर अपने डेटा फ्रेम का विस्तार करना चाहता हूं। मेरा डीएफ इस तरह दिखता है:
item index_start index_end
A 1 3
B 4 7
मैं चाहता हूं कि ए के लिए पंक्तियों को 1 से 3 तक और पंक्तियों को 4 से 7 तक पंक्तियों को बनाने के लिए विस्तारित किया जाए।
item index_start index_end index
A 1 3 1
A 1 3 2
A 1 3 3
B 4 7 4
B 4 7 5
B 4 7 6
B 4 7 7
यह सुनिश्चित नहीं है कि इसे पायथन/पांडा में कैसे कार्यान्वित किया जाए।
3 जवाब
आप .explode()
का उपयोग कर सकते हैं
df['index'] = df.apply(lambda row: list(range(row['index_start'], row['index_end']+1)), axis=1)
df.explode('index')
item index_start index_end index
0 A 1 3 1
0 A 1 3 2
0 A 1 3 3
1 B 4 7 4
1 B 4 7 5
1 B 4 7 6
1 B 4 7 7
हम उपयोग कर सकते हैं pd.Index.repeat
index_end - index_start + 1 बार दोहराने के लिए rel="nofollow noreferrer">df.reindex
। फिर index_start और index_end
के बीच डेटा जेनरेट करें >itertools.starmap
.
from itertools import starmap
rep = (df['index_end'] - df['index_start']) + 1
idx = df.index.repeat(rep)
vals = df.to_numpy()[:, 1:]
vals[:, 1] += 1
index = np.hstack([*starmap(np.arange, vals)])
df.reindex(idx).assign(index=index)
item index_start index_end index
0 A 1 3 1
0 A 1 3 2
0 A 1 3 3
1 B 4 7 4
1 B 4 7 5
1 B 4 7 6
1 B 4 7 7
@Andreas का एक अच्छा पठनीय समाधान है लेकिन दो अड़चन संचालन हैं जो रनटाइम को बढ़ाएंगे एक df.apply
अक्ष 1 और df.explode
पर।
समय विश्लेषण:
बेंचमार्किंग सेटअप:
df = pd.concat([df]*1000, ignore_index=True)
# @Ch3steR's solution
In [130]: %%timeit
...: rep = (df['index_end'] - df['index_start']) + 1
...: idx = df.index.repeat(rep)
...: vals = df.to_numpy()[:, 1:]
...: vals[:, 1] += 1
...: index = np.hstack([*starmap(np.arange, vals)])
...: df.reindex(idx).assign(index=index)
...:
...:
4.82 ms ± 72.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# @Andreas' solution
In [131]: %%timeit
...: df['index'] = df.apply(lambda row: list(range(row['index_start'], row[
...: 'index_end']+1)), axis=1)
...: df.explode('index')
...:
...:
20.4 ms ± 796 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
मैंने कुछ बार परीक्षण चलाया, मेरा समाधान लगभग ~ 4 गुना तेज है। हम गति में और सुधार कर सकते हैं यदि हम किसी तरह index = np.hstack([*starmap(np.arange, vals)])
इस ऑपरेशन को वेक्टरकृत कर सकें।
FWIW, Ch3steR का अच्छा जवाब पर एक छोटा सा अनुकूलन एक ग्रुपबाय करके और एक लेकर index
कॉलम बनाना है प्रत्येक समूह की संचयी गणना, और फिर index_start
द्वारा गणना की भरपाई करना:
rep = (df['index_end'] - df['index_start']) + 1
res = df.loc[df.index.repeat(rep)]
res['index'] = res.groupby(res.index).cumcount() + res['index_start']
आउटपुट (res
):
item index_start index_end index
0 A 1 3 1
0 A 1 3 2
0 A 1 3 3
1 B 4 7 4
1 B 4 7 5
1 B 4 7 6
1 B 4 7 7
और समय, एक ला Ch3steR:
df = pd.concat([df]*1000, ignore_index=True)
%%timeit
rep = (df['index_end'] - df['index_start']) + 1
res = df.loc[df.index.repeat(rep)]
res['index'] = res.groupby(res.index).cumcount() + res['index_start']
# 1.66 ms ± 38.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
आपको विश्वास करना होगा कि अन्य दृष्टिकोणों के लिए मेरा समय पोस्ट किए गए के समान है:)
लेकिन मेरे लिए, यह एक इंडेक्स बनाने के लिए ओवरकिल जैसा लगता है। यदि आपकी मूल पंक्तियों में संदर्भित सूचकांक हमेशा सन्निहित और गैर-अतिव्यापी होते हैं (अर्थात यदि एक प्रविष्टि i से j तक फैली हुई है, तो अगली j + 1< से शुरू होती है। /em>), तो index
केवल पूर्णांकों की एक श्रृंखला होने जा रहा है। तो इसे range
के साथ बनाना सही होना चाहिए:
res['index'] = np.arange(1, len(df) + 1)
या शायद कार्यात्मक रूप से समान रूप से, आप केवल index
बनाने के बजाय DataFrame की अनुक्रमणिका को रीसेट कर सकते हैं:
res = res.reset_index(drop=True)
आपके उदाहरण इनपुट से ऐसा लगता है कि यह पर्याप्त होगा। लेकिन काउंटर केस होगा यदि आपके index_start
और index_end
का अर्थ शाब्दिक पंक्ति संख्या नहीं है, और चीजों को दोहराने के तरीके की गणना करने के लिए अधिक उपयोग किया जाता है। तो उदाहरण के लिए, यदि आपका डेटा ऐसा दिखता है:
# now there are gaps in the indices, and it doesn't start at 1
df = pd.DataFrame({'item':['A','B'],
'index_start':[3, 5],
'index_end':[19, 22]})
लेकिन आप अभी भी चाहते थे कि पहली पंक्ति 3 बार और दूसरी 4 बार दोहराई जाए, और आप वह index
कॉलम बनाना चाहते थे (इस मामले में, [3,4,5,19,20,21,22]
), आपको ग्रुपबाय ऑपरेशन करने की आवश्यकता होगी या कुछ इसी तरह।
संबंधित सवाल
जुड़े हुए प्रश्न
नए सवाल
python
पायथन एक बहु-प्रतिमान है, गतिशील रूप से टाइप किया हुआ, बहुउद्देशीय प्रोग्रामिंग भाषा है। यह एक साफ और एक समान वाक्यविन्यास सीखने, समझने और उपयोग करने के लिए त्वरित होने के लिए डिज़ाइन किया गया है। कृपया ध्यान दें कि अजगर 2 आधिकारिक तौर पर 01-01-2020 के समर्थन से बाहर है। फिर भी, संस्करण-विशिष्ट पायथन सवालों के लिए, [अजगर -२.०] या [अजगर -३.x] टैग जोड़ें। पायथन वेरिएंट (जैसे, ज्योथन, PyPy) या लाइब्रेरी (उदा।, पांडस और न्यूमपी) का उपयोग करते समय, कृपया इसे टैग में शामिल करें।