【问题标题】:pandas int or float column to percentage distributionpandas int 或 float 列到百分比分布
【发布时间】:2019-12-01 20:10:20
【问题描述】:

我有一个熊猫数据框 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 有一个1 在不同的列?

标签: python python-3.x pandas numpy


【解决方案1】:

这是使用pd.cut的一种方式

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

【讨论】:

    【解决方案2】:

    设置

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

    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 个,您可以将第一个差异或最后一个差异分别附加到数组的开头或结尾。它看起来很笨拙,可能有办法避免这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-06
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 2020-10-10
      • 2022-06-13
      • 1970-01-01
      相关资源
      最近更新 更多