কীভাবে একটি পান্ডাস ডেটা ফ্রেমে একটি কলাম আনইস্ট (বিস্ফোরণ) করা যায়?


116

আমার কাছে নিম্নলিখিত ডেটা ফ্রেম রয়েছে যেখানে কলামগুলির মধ্যে একটিতে একটি অবজেক্ট (তালিকার ধরণের ঘর) রয়েছে:

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
সম্পর্কিত unnesting স্ট্রিং: stackoverflow.com/q/48197234/4909087
cs95

5
সম্পর্কিত পোস্টের দম্পতি: এখানে , এখানে , এখানে , এখানে , ...
ক্লিব

উত্তর:


182

Rএবং উভয়ই একজন ব্যবহারকারী হিসাবে pythonআমি এই ধরণের প্রশ্নটি বেশ কয়েকবার দেখেছি।

আর, তারা প্যাকেজ থেকে বিল্ট-ইন ফাংশন আছে tidyrবলা unnest। কিন্তু মধ্যে Python(pandas ) এ এই ধরণের প্রশ্নের কোনও অন্তর্নির্মিত ফাংশন নেই।

আমি জানি objectকলামগুলি typeসবসময় ডেটাটিকে একটি pandas'ফাংশন দিয়ে রূপান্তর করতে শক্ত করে তোলে । আমি যখন এই জাতীয় ডেটা পেয়েছি তখন প্রথম যে বিষয়টি মনে পড়েছিল তা হ'ল চ্যাপ্টা করা বা কলামগুলি আনস্টন করা।

আমি এই ধরণের প্রশ্নের জন্য ব্যবহার করছি pandasএবং pythonফাংশন করছি। আপনি যদি উপরের সমাধানগুলির গতি সম্পর্কে উদ্বিগ্ন হন তবে ব্যবহারকারী 3483203 এর উত্তরটি পরীক্ষা করুন, যেহেতু তিনি ব্যবহার করছেন 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 ) ব্যবহার করি তবে আমাদের পক্ষে কলামগুলি একে একে পুনরায় তৈরি করা শক্ত hard

সমাধান: joinবা mergeসঙ্গে indexপরে 'unnest' একক কলাম

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


বেস ফাংশনটি ব্যবহার করে 7 পদ্ধতিitertools 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কনস্ট্রাক্টরের সাথে পরীক্ষা করুন Check

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। এছাড়াও, এর মধ্যে কয়েকটি বিস্তৃত ডেটাফ্রেমে সাধারণকরণের চেষ্টা করে। যেগুলি দাবী করে তাদের কাছে আপনার ডিএফের কয়টি কলাম আগে সময়ের চেয়ে বেশি তা জানতে হবে।
ত্রিস্তান ব্রাউন

@ ত্রিস্তানব্রাউন কি আপনার শূন্য মাত্রা রয়েছে, আপনার বিস্ফোরণটি পাস করা উচিত নয়, বিস্ফোরণের আগে আপনি এটি ফেলে দেওয়া উচিত, উদাহরণস্বরূপ []ড্রপ করা উচিত, আপনি কি সত্যই উদাহরণটি চেষ্টা করেছিলেন, আমার থেকে? নাকি আপনার আলাদা পরিস্থিতি আছে?
BEN_YO

1
@ ত্রিস্তানব্রাউন পান্ডার বিল্ড-ইন ফাংশনও বিস্ফোরিত হয়েছে, যদি এটি আপনার পক্ষে কাজ না করে, তবে আপনার প্রশ্নটি আলাদা।
BEN_YO

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পদ্ধতির সাথে তুলনা জানলে ভাল লাগবে ।
পল রাউজিউক্স


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

আমি এই পদ্ধতি সম্পর্কে কোন মতামত ভেবেছিলাম? বা কনটাক্ট এবং গলিত উভয়ই খুব "ব্যয়বহুল" হিসাবে বিবেচিত হচ্ছে?


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

আমার ক্ষেত্রে একাধিক কলাম বিস্ফোরিত হওয়ার সাথে, এবং অ্যারেগুলির জন্য ভেরিয়েবলের দৈর্ঘ্য যা অপরিবর্তিত হওয়া দরকার।

আমি নতুন পান্ডাস 0.25 explodeফাংশনটি দুইবার প্রয়োগ করে শেষ করেছি , তারপরে উত্পন্ন নকলগুলি সরিয়ে ফেলছি এবং এটি কাজটি করে!

df = df.explode('A')
df = df.explode('B')
df = df.drop_duplicates()

0

যখন আপনার একাধিক কলাম বিস্ফোরিত হবে তখন এটি সমাধান করার আমার কাছে আরও একটি ভাল উপায় have

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 ডিএফএসে একটি সূচক যোগদান করব।

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])
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.