在Pandas DataFrame中拆分列列表

时间:2017-10-25 22:11:26

标签: python-3.x pandas dataframe pandas-groupby

我正在寻找解决以下问题的好方法。我目前的修复并不是特别干净,我希望从你的见解中学习。

假设我有一个Panda DataFrame,其条目如下所示:

>>> df=pd.DataFrame(index=[1,2,3],columns=['Color','Texture','IsGlass'])

>>> df['Color']=[np.nan,['Red','Blue'],['Blue', 'Green', 'Purple']]
>>> df['Texture']=[['Rough'],np.nan,['Silky', 'Shiny', 'Fuzzy']]
>>> df['IsGlass']=[1,0,1]

>>> df
                            Color                   Texture   IsGlass
    1                         NaN                  ['Rough']        1
    2              ['Red', 'Blue']                       NaN        0 
    3  ['Blue', 'Green', 'Purple']  ['Silky','Shiny','Fuzzy']       1

所以索引中的每个观察对应于我测量的颜色,纹理以及它是否是玻璃的东西。我想做的是将其转换为一个新的“指标”DataFrame,为每个观察值创建一个列,如果我观察它,则将相应的条目更改为一个,如果我没有信息,则将NaN更改为NaN。

>>> df
         Red Blue Green Purple Rough Silky Shiny Fuzzy Is Glass               
    1    Nan  Nan  Nan   Nan    1     NaN   Nan   Nan     1        
    2     1    1   Nan   Nan    Nan   Nan   Nan   Nan     0 
    3    Nan   1    1     1     Nan    1     1     1      1

我有解决方案在每列上循环,查看其值,并通过一系列非Nan值的Try / Excepts拆分列表,创建新列等,并连接。

这是我发给StackOverflow的第一篇文章 - 我希望这篇文章符合发布指南。谢谢。

3 个答案:

答案 0 :(得分:4)

堆叠黑客!

from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()

df = df.stack().unstack(fill_value=[])

def b(c):
    d = mlb.fit_transform(c)
    return pd.DataFrame(d, c.index, mlb.classes_)

pd.concat([b(df[c]) for c in ['Color', 'Texture']], axis=1).join(df.IsGlass)

   Blue  Green  Purple  Red  Fuzzy  Rough  Shiny  Silky IsGlass
1     0      0       0    0      0      1      0      0       1
2     1      0       0    1      0      0      0      0       0
3     1      1       1    0      1      0      1      1       1

答案 1 :(得分:2)

我刚刚使用pandasget_dummies

l=[pd.get_dummies(df[x].apply(pd.Series).stack(dropna=False)).sum(level=0) for x in ['Color','Texture']]
pd.concat(l,axis=1).assign(IsGlass=df.IsGlass)
Out[662]: 
   Blue  Green  Purple  Red  Fuzzy  Rough  Shiny  Silky  IsGlass
1     0      0       0    0      0      1      0      0        1
2     1      0       0    1      0      0      0      0        0
3     1      1       1    0      1      0      1      1        1

答案 2 :(得分:1)

对于每行中的每个纹理/颜色,我检查该值是否为null。如果没有,我们将该值添加为该行的列= 1.

import numpy as np
import pandas as pd

df=pd.DataFrame(index=[1,2,3],columns=['Color','Texture','IsGlass'])

df['Color']=[np.nan,['Red','Blue'],['Blue', 'Green', 'Purple']]
df['Texture']=[['Rough'],np.nan,['Silky', 'Shiny', 'Fuzzy']]
df['IsGlass']=[1,0,1]

for row in df.itertuples():

    if not np.all(pd.isnull(row.Color)):
        for val in row.Color:
            df.loc[row.Index,val] = 1     

    if not np.all(pd.isnull(row.Texture)):
        for val in row.Texture:
            df.loc[row.Index,val] = 1