仅计算数据框中没有 NaN 值的数据行的平均值
Only calculate mean of data rows in dataframe with no NaN-values
我有一个数据框,其中包含客户 ID 及其 2014-2018 年的费用。我想要的是数据框中每个 ID 的 2014-2018 年费用的平均值。
但是有一个条件:如果行 (2014-2018) 中的一个单元格为空,则应返回 NaN。所以我只希望在 2014-2018 列中的所有 5 个行单元格都具有数值时计算平均值。
初始数据帧:
2014 2015 2016 2017 2018 ID
100 122.0 324 632 NaN 12.0
120 159.0 54 452 541.0 96.0
NaN 164.0 687 165 245.0 20.0
180 421.0 512 184 953.0 73.0
110 654.0 913 173 103.0 84.0
130 NaN 754 124 207.0 26.0
170 256.0 843 97 806.0 87.0
140 754.0 95 101 541.0 64.0
80 985.0 184 84 90.0 11.0
96 65.0 127 130 421.0 34.0
期望输出
2014 2015 2016 2017 2018 ID mean
100 122.0 324 632 NaN 12.0 NaN
120 159.0 54 452 541.0 96.0 265.20
NaN 164.0 687 165 245.0 20.0 NaN
180 421.0 512 184 953.0 73.0 450.00
110 654.0 913 173 103.0 84.0 390.60
130 NaN 754 124 207.0 26.0 NaN
170 256.0 843 97 806.0 87.0 434.40
140 754.0 95 101 541.0 64.0 326.20
80 985.0 184 84 90.0 11.0 284.60
96 65.0 127 130 421.0 34.0 167.80
尝试过的代码: -> 然而,这只给出了平均值,忽略了 NaN 条件。他们是否有一些简短的 lambda 函数可以将条件添加到代码中?
import pandas as pd
import numpy as np
data = pd.DataFrame({"ID": [12,96,20,73,84,26,87,64,11,34],
"2014": [100,120,np.nan,180,110,130,170,140,80,96],
"2015": [122,159,164,421,654,np.nan,256,754,985,65],
"2016": [324,54,687,512,913,754,843,95,184,127],
"2017": [632,452,165,184,173,124,97,101,84,130],
"2018": [np.nan,541,245,953,103,207,806,541,90,421]})
print(data)
fiveyear = ["2014", "2015", "2016", "2017", "2018"] -> if a cell in these rows is empty(NaN), then NaN should be in the new 'mean'-column. I only want the mean when, all 5 cells in the row have a numeric value.
data.loc[:, 'mean'] = data[fiveyear].mean(axis=1)
print(data)
在计算平均值之前使用dropna
删除行。因为 pandas 会在返回结果时对齐索引,而这些行被删除了,这些删除行的结果是 NaN
df['mean'] = df[fiveyear].dropna(how='any').mean(1)
也可以 mask
将结果仅显示为全部非空的那些行
df['mean'] = df[fiveyear].mean(1).mask(df[fiveyear].isnull().any(1))
更像是 hack,但因为您知道您需要所有 5 个值,所以您还可以使用支持 min_count
参数的 sum
,因此任何少于 5 个值的东西都是 NaN
df['mean'] = df[fiveyear].sum(1, min_count=len(fiveyear))/len(fiveyear)
这与@ALollz 的回答相同,但有一种灵活的方法来检测所有列,而不管 df 中有多少年
#get years columns in a list
yearsCols= [c for c in df if c != 'ID']
#calculate mean
df['mean'] = df[yearsCols].dropna(how='any').mean(1)
我有一个数据框,其中包含客户 ID 及其 2014-2018 年的费用。我想要的是数据框中每个 ID 的 2014-2018 年费用的平均值。 但是有一个条件:如果行 (2014-2018) 中的一个单元格为空,则应返回 NaN。所以我只希望在 2014-2018 列中的所有 5 个行单元格都具有数值时计算平均值。
初始数据帧:
2014 2015 2016 2017 2018 ID
100 122.0 324 632 NaN 12.0
120 159.0 54 452 541.0 96.0
NaN 164.0 687 165 245.0 20.0
180 421.0 512 184 953.0 73.0
110 654.0 913 173 103.0 84.0
130 NaN 754 124 207.0 26.0
170 256.0 843 97 806.0 87.0
140 754.0 95 101 541.0 64.0
80 985.0 184 84 90.0 11.0
96 65.0 127 130 421.0 34.0
期望输出
2014 2015 2016 2017 2018 ID mean
100 122.0 324 632 NaN 12.0 NaN
120 159.0 54 452 541.0 96.0 265.20
NaN 164.0 687 165 245.0 20.0 NaN
180 421.0 512 184 953.0 73.0 450.00
110 654.0 913 173 103.0 84.0 390.60
130 NaN 754 124 207.0 26.0 NaN
170 256.0 843 97 806.0 87.0 434.40
140 754.0 95 101 541.0 64.0 326.20
80 985.0 184 84 90.0 11.0 284.60
96 65.0 127 130 421.0 34.0 167.80
尝试过的代码: -> 然而,这只给出了平均值,忽略了 NaN 条件。他们是否有一些简短的 lambda 函数可以将条件添加到代码中?
import pandas as pd
import numpy as np
data = pd.DataFrame({"ID": [12,96,20,73,84,26,87,64,11,34],
"2014": [100,120,np.nan,180,110,130,170,140,80,96],
"2015": [122,159,164,421,654,np.nan,256,754,985,65],
"2016": [324,54,687,512,913,754,843,95,184,127],
"2017": [632,452,165,184,173,124,97,101,84,130],
"2018": [np.nan,541,245,953,103,207,806,541,90,421]})
print(data)
fiveyear = ["2014", "2015", "2016", "2017", "2018"] -> if a cell in these rows is empty(NaN), then NaN should be in the new 'mean'-column. I only want the mean when, all 5 cells in the row have a numeric value.
data.loc[:, 'mean'] = data[fiveyear].mean(axis=1)
print(data)
在计算平均值之前使用dropna
删除行。因为 pandas 会在返回结果时对齐索引,而这些行被删除了,这些删除行的结果是 NaN
df['mean'] = df[fiveyear].dropna(how='any').mean(1)
也可以 mask
将结果仅显示为全部非空的那些行
df['mean'] = df[fiveyear].mean(1).mask(df[fiveyear].isnull().any(1))
更像是 hack,但因为您知道您需要所有 5 个值,所以您还可以使用支持 min_count
参数的 sum
,因此任何少于 5 个值的东西都是 NaN
df['mean'] = df[fiveyear].sum(1, min_count=len(fiveyear))/len(fiveyear)
这与@ALollz 的回答相同,但有一种灵活的方法来检测所有列,而不管 df 中有多少年
#get years columns in a list
yearsCols= [c for c in df if c != 'ID']
#calculate mean
df['mean'] = df[yearsCols].dropna(how='any').mean(1)