熊猫将函数应用于数据框的每一行,以每个条目返回一个或多个新行

时间:2020-03-14 13:39:46

标签: python pandas dataframe lambda

我有一个类似以下的数据集:

import pandas as pd
df = pd.DataFrame([[[{'name': 'Joe', 'age': 32, 'category': 'A'}, {'name': 'Jane', 'age': 35, 'category': 'A'}]],
                   [[{'name': 'Beth', 'age': 33, 'category': 'B'}, {'name': 'Bob', 'age': 32, 'category': 'B'}]],
                   [[{'name': 'John', 'age': 35, 'category': 'C'}]],
                   [[{'name': 'Jill', 'age': 33, 'category': 'D'}]],
                   ], columns=['Entries'])

数据框只有一列(称为“条目”),其中每一行都包含一个或多个词典的列表。

我需要一种方法来将字典中每个键的数据帧转换为一列,并使值显示在那些对应的列中,就像这样:

    age category  name
0  32.0        A   Joe
1  35.0        A  Jane
2  33.0        B  Beth
3  32.0        B   Bob
4  35.0        C  John
5  33.0        D  Jill

目前,我有以下代码可以做到这一点:

df2 = pd.DataFrame()
for idx, row in df.iterrows():
    for entry in row.Entries:
        name = entry['name']
        age = entry['age']
        category = entry['category']

        single_entry = pd.Series({'name': name, 'age': age, 'category': category})
        df2 = df2.append(single_entry, ignore_index=True)

上面的代码可以正常工作,但是在我的实际数据集中却非常慢,该数据集有超过1,000,000行。

我考虑过使用内置的Pandas函数来利用它们的速度提升,例如apply函数,但是我不知道如何将其应用于这个特定问题。

实现上述结果的更有效方法是什么?

3 个答案:

答案 0 :(得分:3)

我建议将列表理解与平坦值一起使用以提高速度:

df = pd.DataFrame([y for x in df['Entries'] for y in x])

另一个想法:

from  itertools import chain

df = pd.DataFrame(chain.from_iterable(df['Entries'].tolist()))

print (df)
   name  age category
0   Joe   32        A
1  Jane   35        A
2  Beth   33        B
3   Bob   32        B
4  John   35        C
5  Jill   33        D

性能,其中示例数据重复10000次,共4万行:

df = pd.concat([df] * 10000, ignore_index=True)

In [222]: %timeit pd.DataFrame([y for x in df['Entries'] for y in x])
66.1 ms ± 770 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [223]: %timeit pd.DataFrame(chain.from_iterable(df['Entries'].tolist()))
60.9 ms ± 691 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [224]: %timeit pd.DataFrame(itertools.chain(*df.Entries.tolist()))
60.8 ms ± 237 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [225]: %timeit pd.DataFrame(sum(df.Entries.tolist(),[]))
3.94 s ± 18.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [226]: %timeit pd.DataFrame(df['Entries'].explode().tolist())
131 ms ± 3.28 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

答案 1 :(得分:2)

如果您要保留记录中的索引,爆炸会有所帮助

s=df['Entries'].explode()
pd.DataFrame(s.tolist(),index=s.index)

   name  age category
0   Joe   32        A
0  Jane   35        A
1  Beth   33        B
1   Bob   32        B
2  John   35        C
3  Jill   33        D

答案 2 :(得分:1)

IIUC

pd.DataFrame(sum(df.Entries.tolist(),[]))

   name  age category
0   Joe   32        A
1  Jane   35        A
2  Beth   33        B
3   Bob   32        B
4  John   35        C
5  Jill   33        D

import itertools
pd.DataFrame(itertools.chain(*df.Entries.tolist()))
   name  age category
0   Joe   32        A
1  Jane   35        A
2  Beth   33        B
3   Bob   32        B
4  John   35        C
5  Jill   33        D
相关问题