我有一个具有两个功能的数据框:gps_height(数字)和区域(分类)。
gps_height包含很多0值,在这种情况下,它们是缺少的值。我想用相干区域的平均值填充0值。
我的推理如下: 1.删除零值并取gps_height的平均值,按区域分组
df[df.gps_height !=0].groupby(['region']).mean()
但是如何用这些平均值替换数据框中的零值?
样本数据:
gps_height区域 0 1390伊林加 1 1400马拉 2 0伊林加 3250伊林加 ...
答案 0 :(得分:1)
使用:
df = pd.DataFrame({'region':list('aaabbbccc'),
'gps_height':[2,3,0,3,4,5,1,0,0]})
print (df)
region gps_height
0 a 2
1 a 3
2 a 0
3 b 3
4 b 4
5 b 5
6 c 1
7 c 0
8 c 0
将0
替换为缺失的值,然后将NAN
替换为fillna
,将mean
替换为GroupBy.transform
每组:
df['gps_height'] = df['gps_height'].replace(0, np.nan)
df['gps_height']=df['gps_height'].fillna(df.groupby('region')['gps_height'].transform('mean'))
print (df)
region gps_height
0 a 2.0
1 a 3.0
2 a 2.5
3 b 3.0
4 b 4.0
5 b 5.0
6 c 1.0
7 c 1.0
8 c 1.0
或过滤掉0
个值,汇总means
并映射所有0
行:
m = df['gps_height'] != 0
s = df[m].groupby('region')['gps_height'].mean()
df.loc[~m, 'gps_height'] = df['region'].map(s)
#alternative
#df['gps_height'] = np.where(~m, df['region'].map(s), df['gps_height'])
print (df)
region gps_height
0 a 2.0
1 a 3.0
2 a 2.5
3 b 3.0
4 b 4.0
5 b 5.0
6 c 1.0
7 c 1.0
8 c 1.0
答案 1 :(得分:1)
我最终遇到了@ahbon提出的相同问题:如果要分组的列超过一个,该怎么办?这是我发现的最接近我的问题的问题。经过认真的斗争,我找到了解决方案。
据我所知(有pandas
个特定的功能可以做类似的事情)这可能不是一种优雅/正统的功能,所以我希望得到一些反馈。
发生了什么
import pandas as pd
import random
random.seed(123)
df = pd.DataFrame({"A":list('a'*4+'b'*4+'c'*4+'d'*4),
"B":list('xy'*8),
"C":random.sample(range(17), 16)})
print(df)
A B C
0 a x 1
1 a y 8
2 a x 16
3 a y 12
4 b x 6
5 b y 4
6 b x 14
7 b y 0
8 c x 13
9 c y 5
10 c x 2
11 c y 9
12 d x 10
13 d y 11
14 d x 3
15 d y 15
首先获取0
值的索引以检索非零数据并按组获取均值。
idx = list(df[df["C"] != 0].index)
data_to_group = df.iloc[idx,]
grouped_data = pd.DataFrame(data_to_group.groupby(["A", "B"])["C"].mean())
现在是棘手的部分。这是给我的印象,它可能是一种更优雅的解决方案:
df
中的行子集合并,其中C
是0
;从第一个删除C
,从第二个删除C
df
的子集,其中C
中没有零。grouped_data = grouped_data.stack().unstack().reset_index()
zero_rows = df[df.C == 0]
zero_rows_replaced = pd.merge(left = zero_rows, right = grouped_data,
how = "left", on=["A", "B"],
suffixes=('_x','')).drop('C_x', axis=1)
zero_rows_replaced = zero_rows_replaced.set_index(zero_rows.index.copy())
df.update(zero_rows_replaced)
print(df)
A B C
0 a x 1
1 a y 8
2 a x 16
3 a y 12
4 b x 6
5 b y 4
6 b x 14
7 b y 4
8 c x 13
9 c y 5
10 c x 2
11 c y 9
12 d x 10
13 d y 11
14 d x 3
15 d y 15