Pandas:根据现有值的分布填充NA值

时间:2017-07-02 03:32:44

标签: python-2.7 python-3.x pandas numpy

我有一个pandas数据框,其中一列sign up有多个空值。 sign up列的分类值包含多个OS,例如iOSandroidweb等。 我想填充现有NA值中的OS值,但应根据OS值的现有分布填充NA值。

实施例: 可以说,数据集的OS值计数分布如下:

signup
android web    14
ios web        16
mac            5
other          3
windows        6
Name: id, dtype: int64

我想根据不同OS值的上述分布来填充NA值。我想要做的是保持当前分布,因为填充Mode值可能会导致结果偏差。 有人可以帮助解决这个问题。

3 个答案:

答案 0 :(得分:8)

你可以使用Numpy的random.choice

之类的东西

从符合您描述的框架开始

import numpy as np
import pandas as pd

print(df)
    id   signup
0    1      mac
1    2      mac
2    3      mac
3    4    other
4    5    other
5    6  windows
6    7  windows
7    8  windows
8    9  windows
9   10      NaN
10  11      NaN
11  12      NaN
12  13      NaN
13  14      NaN

在评论中使用piRSquared的提示更新了 搞清楚目前的分布情况

s = df.signup.value_counts(normalize=True)
print(s)
windows    0.444444
mac        0.333333
other      0.222222
Name: signup, dtype: float64

我们将在我们想要更新的nans过滤器旁边使用布尔索引。此外,我们通过传递索引(windows,mac,other)来使用随机选择,所需的大小和每个注册的分布将用于概率(p)参数。

missing = df['signup'].isnull()
df.loc[missing,'signup'] = np.random.choice(s.index, size=len(df[missing]),p=s.values)
print(df)

    id   signup
0    1      mac
1    2      mac
2    3      mac
3    4    other
4    5    other
5    6  windows
6    7  windows
7    8  windows
8    9  windows
9   10  windows
10  11  windows
11  12  mac
12  13  windows
13  14    other

答案 1 :(得分:1)

首先,我将此作为输入(因为我认为您在问题中错误地命名了我的valuesign up

        signup  value
0  android web   14.0
1      ios web   16.0
2          mac    5.0
3        other    3.0
4      windows    6.0
5      ios web    NaN
6          mac    NaN
7      windows    NaN

知道这个问题可以在一行中解决如下:

b = df.groupby('signup')['value'].first()[df['signup']]

请注意,b的类型为pandas.Series。

但如果您希望输出为具有相同列名称的DataFrame,请按以下步骤操作:

b = pd.DataFrame(df.groupby('signup')['value'].first()[df['signup']],columns=['value']).reset_index()
b.rename({1:'value'})

如果您print(b),则输出:

        signup  value
0  android web   14.0
1      ios web   16.0
2          mac    5.0
3        other    3.0
4      windows    6.0
5      ios web   16.0
6          mac    5.0
7      windows    6.0

答案 2 :(得分:1)

  • 找到空值
  • 来自非空值的样本空值。确保设置replace=True
  • 将采样值分配给空位
isnull = df.signup.isnull()
sample = df.signup.dropna().sample(isnull.sum(), replace=True).values
df.loc[isnull, 'signup'] = sample