我有以下pandas DataFrame
:
ID COL1 COL2
123 1 ABC
123 1 CCC
123 NaN AVV
345 2 FGG
345 NaN FRG
345 NaN FGT
我需要根据相同的Col1
替换ID
中的所有NaN值才能获得此结果:
ID COL1 COL2
123 1 ABC
123 1 CCC
123 1 AVV
345 2 FGG
345 2 FRG
345 2 FGT
我可以编写for
循环,但我的数据集执行脚本需要很长时间。是否有任何条件替换功能?
答案 0 :(得分:1)
如何使用Series.isnull()
选择行和Series.map()
来进行条件替换呢?
import pandas as pd
import numpy as np
df = pd.DataFrame({
'ID': [123, 123, 123, 345, 345, 345],
'COL1': [1, 1, np.nan, 2, np.nan, np.nan],
'COL2':['ABC', 'CCC', 'AVV', 'FGG', 'FRG', 'FGT']},
columns=['ID','COL1', 'COL2'])
print df
mapping = {123: 1, 345: 2}
df.loc[df['COL1'].isnull(), 'COL1'] = df['ID'].map(mapping)
print df
之前:
ID COL1 COL2
0 123 1.0 ABC
1 123 1.0 CCC
2 123 NaN AVV
3 345 2.0 FGG
4 345 NaN FRG
5 345 NaN FGT
后:
ID COL1 COL2
0 123 1.0 ABC
1 123 1.0 CCC
2 123 1.0 AVV
3 345 2.0 FGG
4 345 2.0 FRG
5 345 2.0 FGT
编辑:要以编程方式构建mapping
,您可以使用以下两行代码:
df_unique = df.loc[df['COL1'].notnull()].groupby('ID').nth(0)
mapping = pd.Series(df_unique['COL1'].values, index=df_unique.index).to_dict()
答案 1 :(得分:1)
从以下示例开始:
df = pd.DataFrame({'ID': list(range(10)), 'COL1': [np.random.choice([1,np.nan]) for _ in range(10)]})
df = pd.concat([df]*100000).reset_index(drop = True)
df.head()
# COL1 ID
#0 NaN 0
#1 1.0 1
#2 1.0 2
#3 NaN 3
#4 1.0 4
您可以使用每个组中的向前填充和向后填充方法来填充缺失值:
%timeit df.groupby('ID').ffill().bfill()
1 loop, best of 3: 212 ms per loop
或者另一种方法是按ID
和COL1
对值进行排序,首先对ID
进行排序,然后在每个COL1
内排序ID
,这会导致所有丢失值到每个ID
的末尾,然后您可以使用ffill()
,这似乎比上面的ffill()
,bfill()
方法更快:
%timeit df.sort_values(['ID', 'COL1']).ffill()
10 loops, best of 3: 71.6 ms per loop
如果还有其他不需要的字符串,您可以调用replace方法首先用NaN
替换字符串。例如,如果要填充的数据框中有空字符串。你可以df.replace('', np.nan).sort_values(['ID', 'COL1']).ffill()