pandas int或float列到百分比分布

时间:2019-07-23 18:07:04

标签: python python-3.x pandas numpy

我有一个熊猫数据框df:

import pandas as pd
import numpy as np
data = {'A':[250,100,400,np.nan,300]}
df = pd.DataFrame(data)
print(df)

       A
0  250.0
1  100.0
2  400.0
3    NaN
4  300.0

我想根据列表(值)中的值来转换此数据域(DF)。

values = [0,200,400,600]

在df中,第一个数字为250。它在列表values中介于200和400之间,因此(| 200-250 |)/(400-200)= 0.25和(400-250)/(400 -200)= 0.75。如果缺少数据(np.nan),则必须用0填充行。我要以这种方式将其转换为代表此数据框。

所需数据框:

     0   200   400  600
0  0.0  0.25  0.75  0.0
1  0.5  0.50  0.00  0.0
2  0.0  0.00  1.00  0.0
3  0.0  0.00  0.00  0.0
4  0.0  0.50  0.50  0.0

2 个答案:

答案 0 :(得分:5)

这是使用s=pd.cut(df.A,values).dropna() x=s.map(lambda x : x.left).astype(int).to_frame('V') y=s.map(lambda x : x.right).astype(int).to_frame('V') x['r']=(df.A-x.V)/(y.V-x.V) y['r']=(y.V-df.A)/(y.V-x.V) df1=pd.concat([x,y]).set_index('V',append=True).\ r.unstack(fill_value=0).\ reindex(columns=values,index=df.index,fill_value=0) df1 Out[110]: V 0 200 400 600 0 0.0 0.25 0.75 0.0 1 0.5 0.50 0.00 0.0 2 0.0 1.00 0.00 0.0 3 0.0 0.00 0.00 0.0 4 0.0 0.50 0.50 0.0

的一种方法
  status:any; //<--it's necesary create a variable

  submit() {
    //add the asyncValidator
    this.newPassword.setAsyncValidators(this.validateAsync())

    //call to updateValueAndValidity
    this.newPassword.updateValueAndValidity();

    //store in a variable the status
    this.status=this.newPassword.status

    this.newPassword.statusChanges.pipe(
      takeWhile(()=>this.status=='PENDING')  //<--use takeWhile to unsubscribe
    ).subscribe((status) => {
        this.newPassword.clearAsyncValidators();
        this.status=this.newPassword.status
        if (this.newPassword.valid) //<--check if is valid or not  
          alert('submit')
      })
  }

答案 1 :(得分:4)

设置

这里有很多事情要做。我想提出一种完全“矢量化”的方法,但是开销可能使该解决方案不是您要使用的性能最高的解决方案。选择一种方法之前,请确保在任何时间都包含此设置。

u = df['A'].values
v = np.asarray(values)
nan_u = np.isnan(u)
a = np.where(nan_u, 0, u)

d = v[1:] - v[:-1]
diffs = np.concatenate((d[:1], d))
s = np.searchsorted(v, a)

如果值随处可见,则可以使用矢量化方法计算比率,然后在有效范围之间进行屏蔽。

这假定所有非空值都在min(values)max(values)之间。如果不满足此要求,那么创建掩码m的步骤将失败,并出现索引错误。


m = np.zeros((u.shape[0], v.shape[0]), dtype='i1')
ar = np.arange(m.shape[0])

m[ar, s] = 1
m[ar, s-1] = 1

f = np.abs((v - a[:, None]) / diffs)

final = f * m
final[nan_u] = 0

final

array([[0.  , 0.25, 0.75, 0.  ],
       [0.5 , 0.5 , 0.  , 0.  ],
       [0.  , 1.  , 0.  , 0.  ],
       [0.  , 0.  , 0.  , 0.  ],
       [0.  , 0.5 , 0.5 , 0.  ]])

在此答案中,我不满意的第一步是在其中创造差异:

d = v[1:] - v[:-1]
diffs = np.concatenate((d[:1], d))

您实际上只有3个“差异”,但是由于形状原因您需要4个“差异”,因此可以将第一个差异或最后一个差异分别附加到数组的开头或结尾。似乎很笨拙,也许可以避免这种情况。