【问题标题】:Split pandas dataframe column based on number of digits根据位数拆分熊猫数据框列
【发布时间】:2016-11-16 08:42:51
【问题描述】:

我有一个 pandas 数据框,它有两列键和值,值总是由一个 8 位数字组成,类似于

>df1
key value
10  10000100
20  10000000
30  10100000
40  11110000

现在我需要获取 value 列并将其拆分为存在的数字,这样我的结果就是一个新的数据框

>df_res
key 0 1 2 3 4 5 6 7
10  1 0 0 0 0 1 0 0
20  1 0 0 0 0 0 0 0
30  1 0 1 0 0 0 0 0
40  1 1 1 1 0 0 0 0

我无法更改输入数据格式,我认为最常规的方法是将值转换为字符串并循环遍历每个数字字符并将其放入列表中,但是我正在寻找更优雅和更快的东西,请帮助.

编辑:输入不是字符串,而是整数。

【问题讨论】:

  • 您没有将value 列中的那些元素作为字符串开头吗?否则你怎么会有前导零?
  • 问题已编辑,我在示例中添加前导零不好

标签: python pandas dataframe data-manipulation


【解决方案1】:

这应该可行:

df.value.astype(str).apply(list).apply(pd.Series).astype(int)

【讨论】:

  • 非常感谢,非常适合我的用例
【解决方案2】:

一种方法可能是 -

arr = df.value.values.astype('S8')
df = pd.DataFrame(np.fromstring(arr, dtype=np.uint8).reshape(-1,8)-48)

示例运行 -

In [58]: df
Out[58]: 
   key     value
0   10  10000100
1   20  10000000
2   30  10100000
3   40  11110000

In [59]: arr = df.value.values.astype('S8')

In [60]: pd.DataFrame(np.fromstring(arr, dtype=np.uint8).reshape(-1,8)-48)
Out[60]: 
   0  1  2  3  4  5  6  7
0  1  0  0  0  0  1  0  0
1  1  0  0  0  0  0  0  0
2  1  0  1  0  0  0  0  0
3  1  1  1  1  0  0  0  0

【讨论】:

  • 应该除以 48 而不是 -48 ?
  • @johnsmith Nah,它获得了 ascii 等价物。因此,0 变为 48149。所以,要返回整数,我们减去 48。
【解决方案3】:

假设您的输入存储为字符串并且都具有相同的长度(8,如所提出的),那么以下工作:

df1 = pd.concat([df1,pd.DataFrame(columns=range(8))])
df1[list(range(8))] = df1['Value'].apply(lambda x: pd.Series(list(str(x)),index=range(8)))

【讨论】:

    【解决方案4】:

    矢量化版本是:

    df['value'].astype(str).str.join(' ').str.split(' ', expand=True)
    

    这首先在字符之间引入空格,然后进行拆分。能够使用 str.split 只是一种解决方法(可能没有必要,不确定)。但它相当快:

    df = pd.DataFrame({'value': np.random.randint(10**7, 10**8, 10**4)})
    
    %timeit df['value'].astype(str).str.join(' ').str.split(' ', expand=True)
    10 loops, best of 3: 25.5 ms per loop
    
    %timeit df.value.astype(str).apply(list).apply(pd.Series).astype(int)
    1 loop, best of 3: 1.27 s per loop
    
    %timeit df['value'].apply(lambda x: pd.Series(list(str(x)),index=range(8)))
    1 loop, best of 3: 1.33 s per loop
    
    
    %%timeit
    arr = df.value.values.astype('S8')
    pd.DataFrame(np.fromstring(arr, dtype=np.uint8).reshape(-1,8)-48)
    
    1000 loops, best of 3: 1.14 ms per loop
    

    更新:Divakar's solution 似乎是最快的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-23
      • 2019-10-26
      • 2022-01-17
      • 2018-12-04
      • 1970-01-01
      相关资源
      最近更新 更多