【问题标题】:How to convert a column of string to numerical?如何将一列字符串转换为数字?
【发布时间】:2018-02-15 07:55:48
【问题描述】:

我从查询中得到了这个 pandas 数据框:

|    name    |    event    |
----------------------------
| name_1     | event_1     |
| name_1     | event_2     |
| name_2     | event_1     |

我需要将列事件转换为数字,或者看起来像这样:

| name    | event_1 | event_2 |
-------------------------------
| name_1  | 1       | 0       |
| name_1  | 0       | 1       |
| name_2  | 1       | 0       |

在软件 rapidminer 中,我可以使用“名义到数值”运算符来做到这一点,所以我假设在 python 中转换列的类型应该是有效的,但我可能会弄错。

最后,想法是对具有相同名称的列值进行求和,并生成一个应该如下所示的表:

| name    | event_1 | event_2 |
-------------------------------
| name_1  | 1       | 1       |
| name_2  | 1       | 0       |

有一个函数可以返回预期的结果吗?

重要:我无法对事件进行简单的计数,因为我不知道它们,而且事件对于用户来说是不同的

编辑:谢谢大家,我可以看到有多种方法可以做到这一点,你们能说其中哪一种是最pythonic的方式吗?

【问题讨论】:

    标签: python pandas dataframe numerical


    【解决方案1】:

    一些方法

    1)

    In [366]: pd.crosstab(df.name, df.event)
    Out[366]:
    event   event_1  event_2
    name
    name_1        1        1
    name_2        1        0
    

    2)

    In [367]: df.groupby(['name', 'event']).size().unstack(fill_value=0)
    Out[367]:
    event   event_1  event_2
    name
    name_1        1        1
    name_2        1        0
    

    3)

    In [368]: df.pivot_table(index='name', columns='event', aggfunc=len, fill_value=0)
    Out[368]:
    event   event_1  event_2
    name
    name_1        1        1
    name_2        1        0
    

    4)

    In [369]: df.assign(v=1).pivot(index='name', columns='event', values='v').fillna(0)
    Out[369]:
    event   event_1  event_2
    name
    name_1      1.0      1.0
    name_2      1.0      0.0
    

    【讨论】:

    • 警告: 4) 仅当每个组合都是唯一的且不会聚合时才有效。
    • 另外,用'size' 代替len...df.pivot_table(index='name', columns='event', aggfunc='size', fill_value=0)。我的时间安排做出了这个假设。
    【解决方案2】:

    选项 1
    pir1pir1_5

    df.set_index('name').event.str.get_dummies()
    
            event_1  event_2
    name                    
    name_1        1        0
    name_1        0        1
    name_2        1        0
    

    然后你可以对索引求和

    df.set_index('name').event.str.get_dummies().sum(level=0)
    
            event_1  event_2
    name                    
    name_1        1        1
    name_2        1        0
    

    选项 2
    pir2
    或者你可以点积

    pd.get_dummies(df.name).T.dot(pd.get_dummies(df.event))
    
            event_1  event_2
    name_1        1        1
    name_2        1        0
    

    选项 3
    pir3
    高级模式

    i, r = pd.factorize(df.name.values)
    j, c = pd.factorize(df.event.values)
    n, m = r.size, c.size
    
    b = np.bincount(i * m + j, minlength=n * m).reshape(n, m)
    
    pd.DataFrame(b, r, c)
    
            event_1  event_2
    name_1        1        1
    name_2        1        0
    

    时机

    res.plot(loglog=True)
    

    res.div(res.min(1), 0)
    
                pir1      pir2  pir3      john1     john2      john3
    10      9.948396  3.399913   1.0  20.478368  4.460466  10.642113
    30      9.350524  2.681178   1.0  16.589248  3.847666   9.168907
    100    11.414536  3.079463   1.0  18.076040  4.277752   9.949305
    300    15.769594  2.940529   1.0  16.745889  3.945470   9.069265
    1000   26.869451  2.617564   1.0  12.789570  3.236390   7.279205
    3000   42.229542  2.099541   1.0   8.716600  2.429847   4.785814
    10000  52.571678  1.716088   1.0   4.597598  1.691989   2.800455
    30000  58.644764  1.469827   1.0   2.818744  1.535012   1.929452
    

    函数

    pir1 = lambda df: df.set_index('name').event.str.get_dummies().sum(level=0)
    pir1_5 = lambda df: pd.get_dummies(df.set_index('name').event).sum(level=0)
    pir2 = lambda df: pd.get_dummies(df.name).T.dot(pd.get_dummies(df.event))
    
    def pir3(df):
        i, r = pd.factorize(df.name.values)
        j, c = pd.factorize(df.event.values)
        n, m = r.size, c.size
    
        b = np.bincount(i * m + j, minlength=n * m).reshape(n, m)
    
        return pd.DataFrame(b, r, c)
    
    john1 = lambda df: pd.crosstab(df.name, df.event)
    john2 = lambda df: df.groupby(['name', 'event']).size().unstack(fill_value=0)
    john3 = lambda df: df.pivot_table(index='name', columns='event', aggfunc='size', fill_value=0)
    

    测试

    res = pd.DataFrame(
        index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
        columns='pir1 pir2 pir3 john1 john2 john3'.split(),
        dtype=float
    )
    
    for i in res.index:
        d = pd.concat([df] * i, ignore_index=True)
        for j in res.columns:
            stmt = '{}(d)'.format(j)
            setp = 'from __main__ import d, {}'.format(j)
            res.at[i, j] = timeit(stmt, setp, number=100)
    

    【讨论】:

      【解决方案3】:

      您要求的是 pythonic 方式,我认为在 python 中这种方式是使用一种称为 one-hot encoding 的技术,该技术在 sklearn 等库中得到了很好的实现,经过一次热编码后,您将需要按第一列对数据框进行分组并应用 sum 函数。

      这是一个代码:

      import pandas as pd #the useful libraries
      import numpy as np
      from sklearn.preprocessing import LabelBinarizer #form sklmearn
      dataset = pd.DataFrame([['name_1', 'event_1' ], ['name_1', 'event_2'], ['name_2', 'event_1']], columns=['name', 'event'], index=[1, 2, 3])
      data = dataset['event'] #just reproduce your dataframe
      enc = LabelBinarizer(neg_label=0)
      dataset['event_2'] = enc.fit_transform(data)
      event_two = dataset['event_2']
      dataset['event_1'] = (~event_two.astype(np.bool)).astype(np.int64) #this is a tip to reproduce the event_1 columns
      dataset = dataset.groupby('name').sum()
      dataset.reset_index(inplace=True)
      

      输出是:

      【讨论】:

        猜你喜欢
        • 2017-12-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-16
        • 1970-01-01
        • 1970-01-01
        • 2018-05-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多