एक पांडा में एक स्तंभ को अनावश्यक (विस्फोट) कैसे करें DataFrame?


118

मेरे पास निम्नलिखित DataFrame है जहाँ एक कॉलम एक ऑब्जेक्ट (सूची प्रकार सेल) है:

df=pd.DataFrame({'A':[1,2],'B':[[1,2],[1,2]]})
df
Out[458]: 
   A       B
0  1  [1, 2]
1  2  [1, 2]

मेरा अपेक्षित आउटपुट है:

   A  B
0  1  1
1  1  2
3  2  1
4  2  2

इसे प्राप्त करने के लिए मुझे क्या करना चाहिए?


संबंधित प्रश्न

पांडा: जब सेल सामग्री सूचीबद्ध होती है, तो सूची में प्रत्येक तत्व के लिए एक पंक्ति बनाएं

अच्छा प्रश्न और उत्तर लेकिन केवल एक कॉलम को सूची के साथ संभालें (मेरे उत्तर में सेल्फ-डेफ़ फ़ंक्शन कई कॉलमों के लिए काम करेगा, स्वीकृत उत्तर भी सबसे अधिक समय लेने वाले का उपयोग करता है apply, जिसकी अनुशंसा नहीं की जाती है, अधिक जानकारी की जाँच करें मुझे कब चाहिए? मेरे कोड में पांडा लागू करने के लिए कैसे? )


5
संबंधित, अनावश्यक तार: stackoverflow.com/q/48197234/4909087
cs95

5
संबंधित पदों के युगल: यहां , यहां , यहां , यहां , ...
क्लैब

जवाबों:


184

दोनों के साथ एक उपयोगकर्ता के रूप में Rऔर python, मैंने इस प्रकार का प्रश्न एक दो बार देखा है।

आर में, उनके पास अंतर्निहित फ़ंक्शन है tidyrजिसे पैकेज कहा जाता है unnest। लेकिन Python( pandas) इस प्रकार के प्रश्न के लिए कोई अंतर्निहित कार्य नहीं है।

मुझे पता है कि objectकॉलम typeहमेशा pandas'फ़ंक्शन के साथ कनवर्ट करने के लिए डेटा को कठिन बनाते हैं । जब मुझे इस तरह का डेटा मिला, तो पहली बात जो मन में आई, वह थी 'चपटा' या स्तंभों को बेकार करना।

मैं इस प्रकार के प्रश्न के लिए उपयोग कर रहा हूं pandasऔर pythonकार्य कर रहा हूं । यदि आप उपरोक्त समाधानों की गति के बारे में चिंतित हैं, तो user3483203 के उत्तर की जांच करें, क्योंकि वह उपयोग कर रहा है numpyऔर अधिकांश समय numpyतेज है। मैं सुझाव देता हूं Cpythonऔर numbaयदि आपके मामले में गति मायने रखती है।


विधि 0 [पांडा> = 0.25] पांडा 0.25
से शुरू , अगर आपको केवल एक कॉलम को विस्फोट करने की आवश्यकता है, तो आप फ़ंक्शन का उपयोग कर सकते हैं :explode

df.explode('B')

       A  B
    0  1  1
    1  1  2
    0  2  1
    1  2  2

विधि 1
apply + pd.Series (समझने में आसान लेकिन अनुशंसित नहीं है।)

df.set_index('A').B.apply(pd.Series).stack().reset_index(level=0).rename(columns={0:'B'})
Out[463]: 
   A  B
0  1  1
1  1  2
0  2  1
1  2  2

विधि 2 कंस्ट्रक्टर के साथ
प्रयोग करके , अपना डेटाफ़्रेम पुनः बनाएं (प्रदर्शन में अच्छा, कई कॉलम में अच्छा नहीं)repeatDataFrame

df=pd.DataFrame({'A':df.A.repeat(df.B.str.len()),'B':np.concatenate(df.B.values)})
df
Out[465]: 
   A  B
0  1  1
0  1  2
1  2  1
1  2  2

विधि 2.1
उदाहरण के लिए ए के अलावा हमारे पास ए 1 है ..... एक अगर हम अभी भी विधि ( विधि 2 ) का उपयोग करते हैं, तो हमारे लिए एक-एक करके स्तंभों को फिर से बनाना मुश्किल है।

समाधान: joinया एकल कॉलम mergeके indexबाद 'अनावश्यक' के साथ

s=pd.DataFrame({'B':np.concatenate(df.B.values)},index=df.index.repeat(df.B.str.len()))
s.join(df.drop('B',1),how='left')
Out[477]: 
   B  A
0  1  1
0  2  1
1  1  2
1  2  2

यदि आपको पहले की तरह स्तंभ क्रम की आवश्यकता है, reindexतो अंत में जोड़ें ।

s.join(df.drop('B',1),how='left').reindex(columns=df.columns)

विधि 3 को
फिर से बनाएँlist

pd.DataFrame([[x] + [z] for x, y in df.values for z in y],columns=df.columns)
Out[488]: 
   A  B
0  1  1
1  1  2
2  2  1
3  2  2

यदि दो से अधिक कॉलम हैं, तो उपयोग करें

s=pd.DataFrame([[x] + [z] for x, y in zip(df.index,df.B) for z in y])
s.merge(df,left_on=0,right_index=True)
Out[491]: 
   0  1  A       B
0  0  1  1  [1, 2]
1  0  2  1  [1, 2]
2  1  1  2  [1, 2]
3  1  2  2  [1, 2]

विधि 4
का उपयोग कर reindex याloc

df.reindex(df.index.repeat(df.B.str.len())).assign(B=np.concatenate(df.B.values))
Out[554]: 
   A  B
0  1  1
0  1  2
1  2  1
1  2  2

#df.loc[df.index.repeat(df.B.str.len())].assign(B=np.concatenate(df.B.values))

विधि 5
जब सूची में केवल अनन्य मान हैं:

df=pd.DataFrame({'A':[1,2],'B':[[1,2],[3,4]]})
from collections import ChainMap
d = dict(ChainMap(*map(dict.fromkeys, df['B'], df['A'])))
pd.DataFrame(list(d.items()),columns=df.columns[::-1])
Out[574]: 
   B  A
0  1  1
1  2  1
2  3  2
3  4  2

विधि 6 उच्च प्रदर्शन के लिए
उपयोग कर numpyरहा है:

newvalues=np.dstack((np.repeat(df.A.values,list(map(len,df.B.values))),np.concatenate(df.B.values)))
pd.DataFrame(data=newvalues[0],columns=df.columns)
   A  B
0  1  1
1  1  2
2  2  1
3  2  2


बेस फंक्शन का उपयोग करते हुए विधि 7itertools cycle और chain: केवल मनोरंजन के लिए शुद्ध अजगर समाधान

from itertools import cycle,chain
l=df.values.tolist()
l1=[list(zip([x[0]], cycle(x[1])) if len([x[0]]) > len(x[1]) else list(zip(cycle([x[0]]), x[1]))) for x in l]
pd.DataFrame(list(chain.from_iterable(l1)),columns=df.columns)
   A  B
0  1  1
1  1  2
2  2  1
3  2  2

कई कॉलम के लिए सामान्यीकरण

df=pd.DataFrame({'A':[1,2],'B':[[1,2],[3,4]],'C':[[1,2],[3,4]]})
df
Out[592]: 
   A       B       C
0  1  [1, 2]  [1, 2]
1  2  [3, 4]  [3, 4]

आत्म-समारोह:

def unnesting(df, explode):
    idx = df.index.repeat(df[explode[0]].str.len())
    df1 = pd.concat([
        pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1)
    df1.index = idx

    return df1.join(df.drop(explode, 1), how='left')


unnesting(df,['B','C'])
Out[609]: 
   B  C  A
0  1  1  1
0  2  2  1
1  3  3  2
1  4  4  2

स्तंभ-वार उन्नाव

उपरोक्त सभी विधि ऊर्ध्वाधर अनावश्यक और विस्फोट के बारे में बात कर रही है, यदि आपको सूची को क्षैतिज रूप से खर्च करने की आवश्यकता है, तो pd.DataFrameनिर्माता के साथ जांचें

df.join(pd.DataFrame(df.B.tolist(),index=df.index).add_prefix('B_'))
Out[33]: 
   A       B       C  B_0  B_1
0  1  [1, 2]  [1, 2]    1    2
1  2  [3, 4]  [3, 4]    3    4

अद्यतन समारोह

def unnesting(df, explode, axis):
    if axis==1:
        idx = df.index.repeat(df[explode[0]].str.len())
        df1 = pd.concat([
            pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1)
        df1.index = idx

        return df1.join(df.drop(explode, 1), how='left')
    else :
        df1 = pd.concat([
                         pd.DataFrame(df[x].tolist(), index=df.index).add_prefix(x) for x in explode], axis=1)
        return df1.join(df.drop(explode, 1), how='left')

टेस्ट आउटपुट

unnesting(df, ['B','C'], axis=0)
Out[36]: 
   B0  B1  C0  C1  A
0   1   2   1   2  1
1   3   4   3   4  2

ये वास्तव में काम नहीं करते हैं। ValueError: zero-dimensional arrays cannot be concatenated। इसके अलावा, इनमें से कुछ भी एक व्यापक डेटाफ़ॉर्म के सामान्यीकरण का प्रयास करते हैं। जो लोग दावा करते हैं कि आपको यह जानने की आवश्यकता है कि आपके df के पास समय से पहले कितने कॉलम हैं।
ट्रिस्टन ब्राउन

@TristanBrown क्या आपके पास शून्य आयाम है, आपको विस्फोट नहीं करना चाहिए, आपको इसे विस्फोट से पहले छोड़ देना चाहिए, उदाहरण के लिए []छोड़ देना चाहिए, क्या आपने वास्तव में उदाहरण का प्रयास किया है, मेरा? या आपकी अलग स्थिति है?
बेंज_

1
@TristanBrown में पांडा का बिल्ड-इन फंक्शन विस्फोट भी होता है, अगर यह आपके लिए काम नहीं करता है, तो इसका मतलब है कि आपका प्रश्न अलग है।
बेंज_

43

विकल्प 1

यदि अन्य कॉलम में सभी उपविभाग समान लंबाई के हैं, तो numpyयहां एक कुशल विकल्प हो सकता है:

vals = np.array(df.B.values.tolist())    
a = np.repeat(df.A, vals.shape[1])

pd.DataFrame(np.column_stack((a, vals.ravel())), columns=df.columns)

   A  B
0  1  1
1  1  2
2  2  1
3  2  2

विकल्प 2

यदि सब्लिस्ट की लंबाई अलग है, तो आपको एक अतिरिक्त कदम की आवश्यकता है:

vals = df.B.values.tolist()
rs = [len(r) for r in vals]    
a = np.repeat(df.A, rs)

pd.DataFrame(np.column_stack((a, np.concatenate(vals))), columns=df.columns)

   A  B
0  1  1
1  1  2
2  2  1
3  2  2

विकल्प 3

मैंने Nस्तंभों और टाइल Mस्तंभों को समतल करने के लिए इसे सामान्य करने के लिए एक शॉट लिया , मैं बाद में इसे और अधिक कुशल बनाने पर काम करूंगा:

df = pd.DataFrame({'A': [1,2,3], 'B': [[1,2], [1,2,3], [1]],
                   'C': [[1,2,3], [1,2], [1,2]], 'D': ['A', 'B', 'C']})

   A          B          C  D
0  1     [1, 2]  [1, 2, 3]  A
1  2  [1, 2, 3]     [1, 2]  B
2  3        [1]     [1, 2]  C

def unnest(df, tile, explode):
    vals = df[explode].sum(1)
    rs = [len(r) for r in vals]
    a = np.repeat(df[tile].values, rs, axis=0)
    b = np.concatenate(vals.values)
    d = np.column_stack((a, b))
    return pd.DataFrame(d, columns = tile +  ['_'.join(explode)])

unnest(df, ['A', 'D'], ['B', 'C'])

    A  D B_C
0   1  A   1
1   1  A   2
2   1  A   1
3   1  A   2
4   1  A   3
5   2  B   1
6   2  B   2
7   2  B   3
8   2  B   1
9   2  B   2
10  3  C   1
11  3  C   1
12  3  C   2

कार्य

def wen1(df):
    return df.set_index('A').B.apply(pd.Series).stack().reset_index(level=0).rename(columns={0: 'B'})

def wen2(df):
    return pd.DataFrame({'A':df.A.repeat(df.B.str.len()),'B':np.concatenate(df.B.values)})

def wen3(df):
    s = pd.DataFrame({'B': np.concatenate(df.B.values)}, index=df.index.repeat(df.B.str.len()))
    return s.join(df.drop('B', 1), how='left')

def wen4(df):
    return pd.DataFrame([[x] + [z] for x, y in df.values for z in y],columns=df.columns)

def chris1(df):
    vals = np.array(df.B.values.tolist())
    a = np.repeat(df.A, vals.shape[1])
    return pd.DataFrame(np.column_stack((a, vals.ravel())), columns=df.columns)

def chris2(df):
    vals = df.B.values.tolist()
    rs = [len(r) for r in vals]
    a = np.repeat(df.A.values, rs)
    return pd.DataFrame(np.column_stack((a, np.concatenate(vals))), columns=df.columns)

समय

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from timeit import timeit

res = pd.DataFrame(
       index=['wen1', 'wen2', 'wen3', 'wen4', 'chris1', 'chris2'],
       columns=[10, 50, 100, 500, 1000, 5000, 10000],
       dtype=float
)

for f in res.index:
    for c in res.columns:
        df = pd.DataFrame({'A': [1, 2], 'B': [[1, 2], [1, 2]]})
        df = pd.concat([df]*c)
        stmt = '{}(df)'.format(f)
        setp = 'from __main__ import df, {}'.format(f)
        res.at[f, c] = timeit(stmt, setp, number=50)

ax = res.div(res.min()).T.plot(loglog=True)
ax.set_xlabel("N")
ax.set_ylabel("time (relative)")

प्रदर्शन

यहां छवि विवरण दर्ज करें


3
दिलचस्प है, नई df.explodeविधि के साथ तुलना जानना अच्छा होगा ।
पॉल रौजीक्स

16

एक सूची की तरह के कॉलम को विस्फोट करना विधि के अतिरिक्त के साथ पांडा 0.25 में काफी सरल किया गया है explode():

df = pd.DataFrame({'A': [1, 2], 'B': [[1, 2], [1, 2]]})
df.explode('B')

बाहर:

   A  B
0  1  1
0  1  2
1  2  1
1  2  2

9

एक विकल्प यह है कि स्तंभ की पंक्तियों पर जालीदार नुस्खा को अनावश्यक रूप से लागू किया जाए:

import numpy as np
import pandas as pd


def unnest(frame, explode):
    def mesh(values):
        return np.array(np.meshgrid(*values)).T.reshape(-1, len(values))

    data = np.vstack(mesh(row) for row in frame[explode].values)
    return pd.DataFrame(data=data, columns=explode)


df = pd.DataFrame({'A': [1, 2], 'B': [[1, 2], [1, 2]]})
print(unnest(df, ['A', 'B']))  # base
print()

df = pd.DataFrame({'A': [1, 2], 'B': [[1, 2], [3, 4]], 'C': [[1, 2], [3, 4]]})
print(unnest(df, ['A', 'B', 'C']))  # multiple columns
print()

df = pd.DataFrame({'A': [1, 2, 3], 'B': [[1, 2], [1, 2, 3], [1]],
                   'C': [[1, 2, 3], [1, 2], [1, 2]], 'D': ['A', 'B', 'C']})

print(unnest(df, ['A', 'B']))  # uneven length lists
print()
print(unnest(df, ['D', 'B']))  # different types
print()

उत्पादन

   A  B
0  1  1
1  1  2
2  2  1
3  2  2

   A  B  C
0  1  1  1
1  1  2  1
2  1  1  2
3  1  2  2
4  2  3  3
5  2  4  3
6  2  3  4
7  2  4  4

   A  B
0  1  1
1  1  2
2  2  1
3  2  2
4  2  3
5  3  1

   D  B
0  A  1
1  A  2
2  B  1
3  B  2
4  B  3
5  C  1

3

मेरे 5 सेंट:

df[['B', 'B2']] = pd.DataFrame(df['B'].values.tolist())

df[['A', 'B']].append(df[['A', 'B2']].rename(columns={'B2': 'B'}),
                      ignore_index=True)

और दूसरा 5

df[['B1', 'B2']] = pd.DataFrame([*df['B']]) # if values.tolist() is too boring

(pd.wide_to_long(df.drop('B', 1), 'B', 'A', '')
 .reset_index(level=1, drop=True)
 .reset_index())

दोनों समान हैं

   A  B
0  1  1
1  2  1
2  1  2
3  2  2

2

क्योंकि आम तौर पर सब लिस्ट की लंबाई अलग-अलग होती है और इसमें शामिल होना / मर्ज करना अधिक कम्प्यूटेशनल महंगा होता है। मैंने अलग-अलग लंबाई की सबलिस्ट और अधिक सामान्य कॉलम के लिए विधि को रिटेन किया।

मल्टीइंडेक्स भी लिखने का एक आसान तरीका होना चाहिए और समान प्रदर्शन के पास होना चाहिए।

हैरानी की बात है, मेरे कार्यान्वयन में समझ में सबसे अच्छा प्रदर्शन किया है।

def stack(df):
    return df.set_index(['A', 'C']).B.apply(pd.Series).stack()


def comprehension(df):
    return pd.DataFrame([x + [z] for x, y in zip(df[['A', 'C']].values.tolist(), df.B) for z in y])


def multiindex(df):
    return pd.DataFrame(np.concatenate(df.B.values), index=df.set_index(['A', 'C']).index.repeat(df.B.str.len()))


def array(df):
    return pd.DataFrame(
        np.column_stack((
            np.repeat(df[['A', 'C']].values, df.B.str.len(), axis=0),
            np.concatenate(df.B.values)
        ))
    )


import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from timeit import timeit

res = pd.DataFrame(
    index=[
        'stack',
        'comprehension',
        'multiindex',
        'array',
    ],
    columns=[1000, 2000, 5000, 10000, 20000, 50000],
    dtype=float
)

for f in res.index:
    for c in res.columns:
        df = pd.DataFrame({'A': list('abc'), 'C': list('def'), 'B': [['g', 'h', 'i'], ['j', 'k'], ['l']]})
        df = pd.concat([df] * c)
        stmt = '{}(df)'.format(f)
        setp = 'from __main__ import df, {}'.format(f)
        res.at[f, c] = timeit(stmt, setp, number=20)

ax = res.div(res.min()).T.plot(loglog=True)
ax.set_xlabel("N")
ax.set_ylabel("time (relative)")

प्रदर्शन

प्रत्येक विधि का सापेक्ष समय


2

मैंने समस्या को थोड़ा और कॉलमों पर लागू करने के लिए सामान्यीकृत किया।

मेरे समाधान का सारांश:

In[74]: df
Out[74]: 
    A   B             C             columnD
0  A1  B1  [C1.1, C1.2]                D1
1  A2  B2  [C2.1, C2.2]  [D2.1, D2.2, D2.3]
2  A3  B3            C3        [D3.1, D3.2]

In[75]: dfListExplode(df,['C','columnD'])
Out[75]: 
    A   B     C columnD
0  A1  B1  C1.1    D1
1  A1  B1  C1.2    D1
2  A2  B2  C2.1    D2.1
3  A2  B2  C2.1    D2.2
4  A2  B2  C2.1    D2.3
5  A2  B2  C2.2    D2.1
6  A2  B2  C2.2    D2.2
7  A2  B2  C2.2    D2.3
8  A3  B3    C3    D3.1
9  A3  B3    C3    D3.2

पूरा उदाहरण:

वास्तविक विस्फोट 3 लाइनों में किया जाता है। बाकी है सौंदर्य प्रसाधन (मल्टी कॉलम विस्फोट, विस्फोट स्तंभ में सूचियों के बजाय तारों का संचालन, ...)।

import pandas as pd
import numpy as np

df=pd.DataFrame( {'A': ['A1','A2','A3'],
                  'B': ['B1','B2','B3'],
                  'C': [ ['C1.1','C1.2'],['C2.1','C2.2'],'C3'],
                  'columnD': [ 'D1',['D2.1','D2.2', 'D2.3'],['D3.1','D3.2']],
                  })
print('df',df, sep='\n')

def dfListExplode(df, explodeKeys):
    if not isinstance(explodeKeys, list):
        explodeKeys=[explodeKeys]
    # recursive handling of explodeKeys
    if len(explodeKeys)==0:
        return df
    elif len(explodeKeys)==1:
        explodeKey=explodeKeys[0]
    else:
        return dfListExplode( dfListExplode(df, explodeKeys[:1]), explodeKeys[1:])
    # perform explosion/unnesting for key: explodeKey
    dfPrep=df[explodeKey].apply(lambda x: x if isinstance(x,list) else [x]) #casts all elements to a list
    dfIndExpl=pd.DataFrame([[x] + [z] for x, y in zip(dfPrep.index,dfPrep.values) for z in y ], columns=['explodedIndex',explodeKey])
    dfMerged=dfIndExpl.merge(df.drop(explodeKey, axis=1), left_on='explodedIndex', right_index=True)
    dfReind=dfMerged.reindex(columns=list(df))
    return dfReind

dfExpl=dfListExplode(df,['C','columnD'])
print('dfExpl',dfExpl, sep='\n')

WeNYoBen के जवाब का श्रेय


2

समस्या सेटअप

मान लें कि इसके भीतर अलग-अलग लंबाई की वस्तुओं के साथ कई कॉलम हैं

df = pd.DataFrame({
    'A': [1, 2],
    'B': [[1, 2], [3, 4]],
    'C': [[1, 2], [3, 4, 5]]
})

df

   A       B          C
0  1  [1, 2]     [1, 2]
1  2  [3, 4]  [3, 4, 5]

जब लंबाई समान होती है, तो हमारे लिए यह मानना ​​आसान है कि अलग-अलग तत्व मेल खाते हैं और एक साथ "ज़िप्ड" होने चाहिए।

   A       B          C
0  1  [1, 2]     [1, 2]  # Typical to assume these should be zipped [(1, 1), (2, 2)]
1  2  [3, 4]  [3, 4, 5]

हालांकि, जब हम अलग-अलग लंबाई की वस्तुओं को देखते हैं तो यह धारणा चुनौती बन जाती है कि क्या हमें "ज़िप" करना चाहिए, यदि हां, तो हम वस्तुओं में से एक में अतिरिक्त कैसे संभालते हैं। या , शायद हम सभी वस्तुओं के उत्पाद चाहते हैं। यह बड़ी तेजी से मिलेगा, लेकिन यह वही हो सकता है जो चाहता है।

   A       B          C
0  1  [1, 2]     [1, 2]
1  2  [3, 4]  [3, 4, 5]  # is this [(3, 3), (4, 4), (None, 5)]?

या

   A       B          C
0  1  [1, 2]     [1, 2]
1  2  [3, 4]  [3, 4, 5]  # is this [(3, 3), (3, 4), (3, 5), (4, 3), (4, 4), (4, 5)]

कार्यक्रम

यह फ़ंक्शन इनायत से संभालता है zipया productएक पैरामीटर के आधार पर होता है और zipसबसे लंबे ऑब्जेक्ट की लंबाई के अनुसार मानता हैzip_longest

from itertools import zip_longest, product

def xplode(df, explode, zipped=True):
    method = zip_longest if zipped else product

    rest = {*df} - {*explode}

    zipped = zip(zip(*map(df.get, rest)), zip(*map(df.get, explode)))
    tups = [tup + exploded
     for tup, pre in zipped
     for exploded in method(*pre)]

    return pd.DataFrame(tups, columns=[*rest, *explode])[[*df]]

ज़िपित

xplode(df, ['B', 'C'])

   A    B  C
0  1  1.0  1
1  1  2.0  2
2  2  3.0  3
3  2  4.0  4
4  2  NaN  5

उत्पाद

xplode(df, ['B', 'C'], zipped=False)

   A  B  C
0  1  1  1
1  1  1  2
2  1  2  1
3  1  2  2
4  2  3  3
5  2  3  4
6  2  3  5
7  2  4  3
8  2  4  4
9  2  4  5

नया सेटअप

उदाहरण को थोड़ा ऊपर उठाते हुए

df = pd.DataFrame({
    'A': [1, 2],
    'B': [[1, 2], [3, 4]],
    'C': 'C',
    'D': [[1, 2], [3, 4, 5]],
    'E': [('X', 'Y', 'Z'), ('W',)]
})

df

   A       B  C          D          E
0  1  [1, 2]  C     [1, 2]  (X, Y, Z)
1  2  [3, 4]  C  [3, 4, 5]       (W,)

ज़िपित

xplode(df, ['B', 'D', 'E'])

   A    B  C    D     E
0  1  1.0  C  1.0     X
1  1  2.0  C  2.0     Y
2  1  NaN  C  NaN     Z
3  2  3.0  C  3.0     W
4  2  4.0  C  4.0  None
5  2  NaN  C  5.0  None

उत्पाद

xplode(df, ['B', 'D', 'E'], zipped=False)

    A  B  C  D  E
0   1  1  C  1  X
1   1  1  C  1  Y
2   1  1  C  1  Z
3   1  1  C  2  X
4   1  1  C  2  Y
5   1  1  C  2  Z
6   1  2  C  1  X
7   1  2  C  1  Y
8   1  2  C  1  Z
9   1  2  C  2  X
10  1  2  C  2  Y
11  1  2  C  2  Z
12  2  3  C  3  W
13  2  3  C  4  W
14  2  3  C  5  W
15  2  4  C  3  W
16  2  4  C  4  W
17  2  4  C  5  W

1

कुछ बहुत अनुशंसित नहीं (कम से कम इस मामले में काम):

df=pd.concat([df]*2).sort_index()
it=iter(df['B'].tolist()[0]+df['B'].tolist()[0])
df['B']=df['B'].apply(lambda x:next(it))

concat+ sort_index+ iter+ apply+ next

अभी:

print(df)

है:

   A  B
0  1  1
0  1  2
1  2  1
1  2  2

यदि सूचकांक के बारे में परवाह है:

df=df.reset_index(drop=True)

अभी:

print(df)

है:

   A  B
0  1  1
1  1  2
2  2  1
3  2  2

1
df=pd.DataFrame({'A':[1,2],'B':[[1,2],[1,2]]})

pd.concat([df['A'], pd.DataFrame(df['B'].values.tolist())], axis = 1)\
  .melt(id_vars = 'A', value_name = 'B')\
  .dropna()\
  .drop('variable', axis = 1)

    A   B
0   1   1
1   2   1
2   1   2
3   2   2

इस विधि के बारे में कोई राय मुझे लगा? या दोनों कॉनैट और पिघल को भी "महंगा" माना जा रहा है?


1

जब आपके पास विस्फोट करने के लिए एक से अधिक कॉलम हों, तो मेरे पास एक और अच्छा तरीका है।

df=pd.DataFrame({'A':[1,2],'B':[[1,2],[1,2]], 'C':[[1,2,3],[1,2,3]]})

print(df)
   A       B          C
0  1  [1, 2]  [1, 2, 3]
1  2  [1, 2]  [1, 2, 3]

मैं कॉलम बी और सी का विस्फोट करना चाहता हूं। पहले मैं बी से विस्फोट करता हूं, दूसरा सी। मैं मूल डीएफ से बी और सी गिराता हूं। उसके बाद मैं 3 dfs पर एक इंडेक्स जॉइन करूंगा।

explode_b = df.explode('B')['B']
explode_c = df.explode('C')['C']
df = df.drop(['B', 'C'], axis=1)
df = df.join([explode_b, explode_c])

0
df=pd.DataFrame({'A':[1,2],'B':[[1,2],[1,2]]})

out = pd.concat([df.loc[:,'A'],(df.B.apply(pd.Series))], axis=1, sort=False)

out = out.set_index('A').stack().droplevel(level=1).reset_index().rename(columns={0:"B"})

       A    B
   0    1   1
   1    1   2
   2    2   1
   3    2   2
  • यदि आप मध्यवर्ती वस्तु बनाने की इच्छा नहीं रखते हैं, तो आप इसे एक लाइनर के रूप में लागू कर सकते हैं

0
# Here's the answer to the related question in:
# https://stackoverflow.com/q/56708671/11426125

# initial dataframe
df12=pd.DataFrame({'Date':['2007-12-03','2008-09-07'],'names':
[['Peter','Alex'],['Donald','Stan']]})

# convert dataframe to array for indexing list values (names)
a = np.array(df12.values)  

# create a new, dataframe with dimensions for unnested
b = np.ndarray(shape = (4,2))
df2 = pd.DataFrame(b, columns = ["Date", "names"], dtype = str)

# implement loops to assign date/name values as required
i = range(len(a[0]))
j = range(len(a[0]))
for x in i:
    for y in j:
        df2.iat[2*x+y, 0] = a[x][0]
        df2.iat[2*x+y, 1] = a[x][1][y]

# set Date column as Index
df2.Date=pd.to_datetime(df2.Date)
df2.index=df2.Date
df2.drop('Date',axis=1,inplace =True)

0

मेरे मामले में विस्फोट करने के लिए एक से अधिक कॉलम के साथ, और वैरिएबल की लंबाई उन सरणियों के लिए है जिन्हें अनावश्यक रूप से रखने की आवश्यकता है।

मैंने explodeदो बार नए पांडा 0.25 फ़ंक्शन को लागू किया , फिर उत्पन्न डुप्लिकेट को हटा दिया और यह काम करता है!

df = df.explode('A')
df = df.explode('B')
df = df.drop_duplicates()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.