如何将一列字符串转换为数字?

时间:2017-09-06 18:09:16

标签: python pandas dataframe numerical

我从查询中获得了这个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       |

在软件快速浏览器中,我可以使用操作符"名义上的数字",所以我假设在python转换中列的类型应该是有效的,但我可能会弄错。

在决赛中,我们的想法是对具有相同名称的列值进行求和,并得到一个如下所示的表:

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

有一个函数可以返回预期的内容吗?

重要的是:我无法对事件进行简单的计算,因为我不了解它们,而且用户的事件也不同

编辑:非常感谢大家,我可以看到有多种方法可以做到这一点,你们能说这些中哪一个是最蟒蛇的方式吗?

3 个答案:

答案 0 :(得分:6)

一些做法

<强> 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

答案 1 :(得分:5)

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

enter image description here

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)

答案 2 :(得分:0)

你要求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)

,输出为:

enter image description here