繁体   English   中英

将值替换为其在总行中的百分比

[英]Replace values by their percentage in total row

用行中的百分比替换某些列中的值的最直接方法是什么?

例:

由此

在此处输入图片说明

对此

在此处输入图片说明

我已经尝试了代码:

cols=['h1', 'h2', 'h3', 'hn']
df[cols]=df[cols]/df['sum']

但这返回错误:

ValueError:列的长度必须与键的长度相同。

另外,我认为这不是最好的方法,因为我的列可能比4多得多。

使用DataFrame.div并指定axis=0

cols=['h1', 'h2', 'h3', 'hn']
df[cols]=df[cols].div(df['sum'], axis=0)

如果sum是最后一列,则可以使用:

df.iloc[:, :-1]=df.iloc[:, :-1].div(df['sum'], axis=0)

样品

df = pd.DataFrame({
         'h1':[4,5,4,5,5,4],
         'h2':[7,8,9,4,2,3],
         'h3':[1,3,5,7,1,0],
         'hn':[4,5,4,5,5,4],
})
df['sum'] = df.sum(axis=1)

df.iloc[:, :-1] = df.iloc[:, :-1].div(df['sum'], axis=0)
print (df)
         h1        h2        h3        hn  sum
0  0.250000  0.437500  0.062500  0.250000   16
1  0.238095  0.380952  0.142857  0.238095   21
2  0.181818  0.409091  0.227273  0.181818   22
3  0.238095  0.190476  0.333333  0.238095   21
4  0.384615  0.153846  0.076923  0.384615   13
5  0.363636  0.272727  0.000000  0.363636   11

性能

np.random.seed(2019)

N = 10000
df = pd.DataFrame(np.random.randint(100, size=(N, 20))).add_prefix('h')
df['sum'] = df.sum(axis=1)
print (df)

In [220]: %%timeit
     ...: df.iloc[:, :-1]=df.iloc[:, :-1].div(df['sum'], axis=0)
     ...: 
8.03 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
C:\Anaconda\lib\site-packages\spyder\widgets\variableexplorer\utils.py:410: FutureWarning: 'summary' is deprecated and will be removed in a future version.
  display = value.summary()

In [221]: %%timeit
     ...: for col in df.columns[:-1]:
     ...:     df[col] /= df["sum"]
     ...: 
9.46 ms ± 168 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
C:\Anaconda\lib\site-packages\spyder\widgets\variableexplorer\utils.py:410: FutureWarning: 'summary' is deprecated and will be removed in a future version.
  display = value.summary()

In [222]: %%timeit
     ...: df.iloc[:,:-1] = df.iloc[:,:-1].apply(lambda x: x/sum(x), axis=1)
     ...: 
2.51 s ± 194 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
C:\Anaconda\lib\site-packages\spyder\widgets\variableexplorer\utils.py:410: FutureWarning: 'summary' is deprecated and will be removed in a future version.
  display = value.summary()

也许更具可读性:

for col in df.columns[:-1]:
    df[col] /= df["sum"]

另一个解决方案:

import pandas as pd

df = pd.DataFrame({
         'h1':[56,4,4,203],
         'h2':[89,67,3,4],
         'h3':[45,23,6,46],
         'hn':[32,44,78,78],
         'sum':[222,138,91,331],
})


df.iloc[:,:-1] = df.iloc[:,:-1].apply(lambda x: x/sum(x), axis=1)

你会得到:

    h1            h2          h3          hn        sum
0   0.252252    0.400901    0.202703    0.144144    222
1   0.028986    0.485507    0.166667    0.318841    138
2   0.043956    0.032967    0.065934    0.857143    91
3   0.613293    0.012085    0.138973    0.235650    331

请注意,此解决方案比jezrael的解决方案要慢得多。

%timeit df.iloc[:,:-1] = df.iloc[:,:-1].apply(lambda x: x/sum(x), axis=1)
%timeit df.iloc[:, :-1]=df.iloc[:, :-1].div(df['sum'], axis=0)

在普通笔记本电脑上,它可以为我提供:

3.33 ms ± 130 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.27 ms ± 1.82 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

慢了将近三倍。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM