Python 随机插入NA';s数据帧中的值-没有完全丢失的行

Python 随机插入NA';s数据帧中的值-没有完全丢失的行,python,pandas,missing-data,Python,Pandas,Missing Data,如何随机地使panda数据框中缺少一些值,如中所示,但确保没有任何行完全设置了缺少的值 Edit:很抱歉没有再次明确说明这一点(这是在我提到的问题中):我需要能够指定多少百分比(例如10%)的单元格应该是NaN(或者更确切地说,接近10%的单元格应该是现有数据帧的大小),而不是,独立地清除单元格,每个单元格的边际概率为10%。应用一个函数来替换随机列的值怎么样。为了避免替换整行,可以绘制一个介于0和n-1之间的数值来替换 import random def add_random_na(row)

如何随机地使panda数据框中缺少一些值,如中所示,但确保没有任何行完全设置了缺少的值


Edit:很抱歉没有再次明确说明这一点(这是在我提到的问题中):我需要能够指定多少百分比(例如10%)的单元格应该是
NaN
(或者更确切地说,接近10%的单元格应该是现有数据帧的大小),而不是,独立地清除单元格,每个单元格的边际概率为10%。

应用一个函数来替换随机列的值怎么样。为了避免替换整行,可以绘制一个介于0和n-1之间的数值来替换

import random

def add_random_na(row):
    vals = row.values
    for _ in range(random.randint(0,len(vals)-2)):
        i = random.randint(0,len(vals)-1)
        vals[i] = np.nan
    return vals

df = df.apply(add_random_na,axis=1)

以下是基于以下方面的答案:

replaced=collections.defaultdict(集合)
ix=[(行,列)表示范围内的行(df.shape[0]),表示范围内的列(df.shape[1])]
随机洗牌(ix)
to_replace=int(圆形(.1*len(ix)))
对于第九行中的列:
如果len(替换的[row])
shuffle操作将导致索引的随机顺序,if子句将避免替换整行。

您可以使用,并且对于
numpy布尔掩码


这是否确保删除正确百分比的单元格?否。我没有看到对替换的确切数量有要求。这是在我提到的问题中。我现在在我的问题中也明确指出了这一点。很抱歉没有从一开始就说清楚。我添加了另一个满足要求的答案。有趣的想法。然而,这有三个问题:1)最后一列得到了比平均数更多的非NaN,2)只是将某些元素变为False,正在扭曲NaN的百分比,3)目前我不知道如何将百分比设置为例如10%。对不起,我不知道百分比。但是可能需要
mask=np.random.choice([True,False],size=df.shape,p=[0.1,0.9])
然后它将是一行中所有
True
值的非常大的数据帧。然后我的答案可以用于
100%
并非所有
True
。似乎都能按预期工作。是否也有10%的细胞是NaN,而替换的概率不是10%?你能解释一下它是怎么工作的吗。我不太确定。首先,它创建所有索引的组合。然后随机洗牌索引。最后,它遍历无序索引并插入nan,直到达到所需的nan数(to_replace=int(round(.1*len(ix)))。在进行任何替换之前,都会验证行中是否未满NAN。如果要更改百分比,请将.1替换为另一个值(例如,0.5表示50%)。如果行中充满了NaN,则该算法将比其他情况多使用一个无序索引?它只计算实际替换,因此最终替换量始终为预期数。
replaced = collections.defaultdict(set)
ix = [(row, col) for row in range(df.shape[0]) for col in range(df.shape[1])]
random.shuffle(ix)
to_replace = int(round(.1*len(ix)))
for row, col in ix:
    if len(replaced[row]) < df.shape[1] - 1:
        df.iloc[row, col] = np.nan
        to_replace -= 1
        replaced[row].add(col)
        if to_replace == 0:
            break
df = pd.DataFrame({'A':[1,2,3],
                   'B':[4,5,6],
                   'C':[7,8,9]})

print (df)
   A  B  C
0  1  4  7
1  2  5  8
2  3  6  9

np.random.seed(100)
mask = np.random.choice([True, False], size=df.shape)
print (mask)
[[ True  True False]
 [False False False]
 [ True  True  True]] -> problematic values - all True

mask[mask.all(1),-1] = 0
print (mask)
[[ True  True False]
 [False False False]
 [ True  True False]]

print (df.mask(mask))
     A    B  C
0  NaN  NaN  7
1  2.0  5.0  8
2  NaN  NaN  9