【问题标题】:How to convert row string values to features如何将行字符串值转换为特征
【发布时间】:2017-07-01 00:29:25
【问题描述】:

我有一个如下所示的数据框。它有 ID 列和每个客户的产品历史记录。

ID      1    2    3    4
1       A    B    C    D
2       E    C    B    D
3       F    B    C    D

我不想为每个客户列出产品,而是将产品转换为特征(列),以便数据框看起来像这样。

ID      A    B    C    D    E    F
1       1    1    1    1    0    0
2       0    0    0    1    1    0
3       0    1    1    1    0    1

我尝试使用 get_dummies 函数,但是,这会将不同的列呈现为 1-A、1-E、1-F、2-B、2-C、...等,这不是我需要的。

关于完成这项工作的任何建议。

【问题讨论】:

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


【解决方案1】:

这会产生你想要的数据框。

df = pd.get_dummies(df.set_index('ID').T.unstack()).groupby(level=0).sum().astype(int)

print (df)

输出:

    A  B  C  D  E  F
ID                  
1   1  1  1  1  0  0
2   0  1  1  1  1  0
3   0  1  1  1  0  1

【讨论】:

    【解决方案2】:

    您可以使用get_dummies 并与max 聚合:

    print (pd.get_dummies(df.set_index('ID'), prefix_sep='', prefix='')
             .groupby(axis=1, level=0).max())
    

    或者:

    print (pd.get_dummies(df.set_index('ID').stack())
             .groupby(level=0).max().astype(int))
    

    你可以使用自定义函数,但是速度很慢:

    df = df.set_index('ID').apply(lambda x: pd.Series(dict(zip(x, [1]*len(df.columns)))), axis=1)
           .fillna(0)
           .astype(int)
    print (df)
        A  B  C  D  E  F
    ID                  
    1   1  1  1  1  0  0
    2   0  1  1  1  1  0
    3   0  1  1  1  0  1
    

    我对时间安排很感兴趣:

    np.random.seed(123)
    N = 10000
    L = list('ABCDEFGHIJKLMNOPQRST')
    #[10000 rows x 20 columns]
    df = pd.DataFrame(np.random.choice(L, size=(N,5)))
    df = df.rename_axis('ID').reset_index()
    print (df.head())
    
    #Alex Fung solution
    In [160]: %timeit (pd.get_dummies(df.set_index('ID').T.unstack()).groupby(level=0).sum().astype(int))
    10 loops, best of 3: 27.9 ms per loop
    
    In [161]: %timeit (pd.get_dummies(df.set_index('ID').stack()).groupby(level=0).max().astype(int))
    10 loops, best of 3: 26.3 ms per loop
    
    In [162]: %timeit (pd.get_dummies(df.set_index('ID'), prefix_sep='', prefix='').groupby(axis=1, level=0).max())
    10 loops, best of 3: 26.4 ms per loop
    
    In [163]: %timeit (df.set_index('ID').apply(lambda x: pd.Series(dict(zip(x, [1]*len(df.columns)))), axis=1).fillna(0).astype(int))
    1 loop, best of 3: 3.95 s per loop
    

    【讨论】:

    • IndentationError: unexpected indent 在 Python 2.7 中提出。
    • 是的,那么只需要像df = df.set_index('ID').apply(lambda x: pd.Series(dict(zip(x, [1]*len(df.columns)))), axis=1).fillna(0).astype(int)这样的一行或在第一行和第二行的末尾添加`\`
    • 你是对的!只是有点令人困惑,因为代码位应该开箱即用。解决问题的好方法!干杯。
    猜你喜欢
    • 2015-05-13
    • 2019-11-13
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 2020-11-05
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    相关资源
    最近更新 更多