为了账号安全,请及时绑定邮箱和手机立即绑定

如何在pandas DataFrame中取消(爆炸)一列?

如何在pandas DataFrame中取消(爆炸)一列?

holdtom 2019-05-29 16:26:50
如何在pandas DataFrame中取消(爆炸)一列?我有以下DataFrame,其中一列是一个对象(列表类型单元格):df=pd.DataFrame({'A':[1,2],'B':[[1,2],[1,2]]})dfOut[458]:    A       B0  1  [1, 2]1  2  [1, 2]我的预期输出是:   A  B0  1  11  1  23  2  14  2  2我该怎么做才能做到这一点?
查看完整描述

3 回答

?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

选项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)")


查看完整回答
反对 回复 2019-05-29
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

另一种方法是将meshgrid配方应用于列的行以免除:


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


查看完整回答
反对 回复 2019-05-29
  • 3 回答
  • 0 关注
  • 964 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信