根据其他列中的值平均某些列
Average certain columns based on values in other columns
我想根据另一列中是否满足条件来计算某些列值的平均值。具体来说,如果下面数据框中的第 1 列 < 1700,我想在我的平均计算中包括第 51 列该行中的相应值。如果第 2 列 < 1700,我还想在我的平均计算中包括第 52 列该行中的值。
因此,对于第 0 行,该行的新计算列将为 64(65 和 63 的平均值)。对于第 1 行,平均值仅为 80(第 51 列值),因为第 2 列和第 3 列均不小于 1700,因此不包括在平均值计算中。
这是一个简化的示例,因为我的实际数据框有大约 10 列条件,其中 10 列对应的值要平均。
作为一个潜在的复杂性,headers 列是数字而不是传统的文本标签,并且不参考数据框中该列的顺序,因为我在导入 csv 文件时排除了某些列.换句话说,第 51 列不是数据框中的第 51 列。
当我 运行 以下代码时,出现以下错误:
ValueError: ("No axis named 1 for object type ",
'occurred at index 0')
有没有更有效的编码方式来避免这个错误?感谢您的帮助!
import pandas as pd
import numpy as np
test_df = pd.DataFrame({1:[1600,1600,1600,1700,1800],2:[1500,2000,1400,1500,2000],
3:[2000,2000,2000,2000,2000],51:[65,80,75,80,75],52:[63,82,85,85,75],53:[83,80,75,76,78]})
test_df
1 2 3 51 52 53
0 1600 1500 2000 65 63 83
1 1600 2000 2000 80 82 80
2 1600 1400 2000 75 85 75
3 1700 1500 2000 80 85 76
4 1800 2000 2000 75 75 78
def calc_mean_based_on_conditions(row):
list_of_columns_to_average = []
for i in range(1,4):
if row[i] < 1700:
list_of_columns_to_average.append(i+50)
if not list_of_columns_to_average:
return np.nan
else:
return row[(list_of_columns_to_average)].mean(axis=1)
test_df['MeanValue'] = test_df.apply(calc_mean_based_on_conditions, axis=1)
我删除了我的另一个答案,因为它走错了路。您要做的是生成条件列的掩码,然后使用该掩码将函数应用于其他列。本例中1对应51,2对应52等
import pandas as pd
import numpy as np
test_df = pd.DataFrame({1:[1600,1600,1600,1700,1800],2:[1500,2000,1400,1500,2000],
3:[2000,2000,2000,2000,2000],51:[65,80,75,80,75],52:[63,82,85,85,75],53:[83,80,75,76,78]})
test_df
1 2 3 51 52 53
0 1600 1500 2000 65 63 83
1 1600 2000 2000 80 82 80
2 1600 1400 2000 75 85 75
3 1700 1500 2000 80 85 76
4 1800 2000 2000 75 75 78
# create dictionary to map columns to one another
l1=list(range(1,4))
l2=list(range(50,54))
d = {k:v for k,v in zip(l1,l2)}
d
{1: 51, 2: 52, 3: 53}
temp=test_df[l1] > 1700 # Subset initial dataframe, generate mask
for _, row in temp.iterrows(): #iterate through subsetted data
list_of_columns_for_mean=list() # list of columns for later computation
for k, v in d.items(): #iterate through each k:v and evaluate conditional for each row
if row[k]:
list_of_columns_for_mean.append(v)
# the rest should be pretty easy to figure out
这不是一个优雅的解决方案,但它是一个解决方案。不幸的是,我 运行 没有时间专注于此,但希望这能让您指明更好的方向。
可能有更好的矢量化方法来执行此操作,但您可以在没有函数
的情况下执行此操作
import numpy as np
import pandas as pd
from collections import defaultdict
test_df = pd.DataFrame({1:[1600,1600,1600,1700,1800],2:[1500,2000,1400,1500,2000],
3:[2000,2000,2000,2000,2000],51:[65,80,75,80,75],52:[63,82,85,85,75],53:[83,80,75,76,78]})
# List of columns that you're applying the condition to
condition_cols = list(range(1,4))
# Get row and column indices where this condition is true
condition = np.where(test_df[condition_cols].lt(1700))
# make a dictionary mapping row to true columns
cond_map = defaultdict(list)
for r,c in zip(*condition):
cond_map[r].append(c)
# Get the means of true columns
means = []
for row in range(len(test_df)):
if row in cond_map:
temp = []
for col in cond_map[row]:
# Needs 51 because of Python indexing starting at zero + 50
temp.append(test_df.loc[row, col+51])
means.append(temp)
else:
# If the row has no true columns (i.e row 4)
means.append(np.nan)
test_df['Means'] = [np.mean(l) for l in means]
问题是以矢量化方式索引真实行 和 列。
一些非常相关的东西(支持 int 作为列名)- https://github.com/theislab/anndata/issues/31
由于这个 bug/issue,我将列名转换为字符串类型:
test_df = pd.DataFrame({'1':[1600,1600,1600,1700,1800],'2':[1500,2000,1400,1500,2000],
'3':[2000,2000,2000,2000,2000],'51':[65,80,75,80,75],'52':[63,82,85,85,75],'53':
[83,80,75,76,78]})
创建了一个新数据框 - new_df 以满足要求
new_df = test_df[['1', '2', '3']].where(test_df[['1','2','3']]<1700).notnull()
new_df 现在看起来像这样
1 2 3
0 True True False
1 True False False
2 True True False
3 False True False
4 False False False
然后只需重命名该列并使用 'where'
进行检查
new_df = new_df.rename(columns={"1": "51", "2":"52", "3":"53"})
test_df['mean_value'] = test_df[['51', '52', '53']].where(new_df).mean(axis=1)
这应该会给你想要的输出 -
1 2 3 51 52 53 mean_value
0 1600 1500 2000 65 63 83 64.0
1 1600 2000 2000 80 82 80 80.0
2 1600 1400 2000 75 85 75 80.0
3 1700 1500 2000 80 85 76 85.0
4 1800 2000 2000 75 75 78 NaN
我想根据另一列中是否满足条件来计算某些列值的平均值。具体来说,如果下面数据框中的第 1 列 < 1700,我想在我的平均计算中包括第 51 列该行中的相应值。如果第 2 列 < 1700,我还想在我的平均计算中包括第 52 列该行中的值。
因此,对于第 0 行,该行的新计算列将为 64(65 和 63 的平均值)。对于第 1 行,平均值仅为 80(第 51 列值),因为第 2 列和第 3 列均不小于 1700,因此不包括在平均值计算中。
这是一个简化的示例,因为我的实际数据框有大约 10 列条件,其中 10 列对应的值要平均。
作为一个潜在的复杂性,headers 列是数字而不是传统的文本标签,并且不参考数据框中该列的顺序,因为我在导入 csv 文件时排除了某些列.换句话说,第 51 列不是数据框中的第 51 列。
当我 运行 以下代码时,出现以下错误:
ValueError: ("No axis named 1 for object type ", 'occurred at index 0')
有没有更有效的编码方式来避免这个错误?感谢您的帮助!
import pandas as pd
import numpy as np
test_df = pd.DataFrame({1:[1600,1600,1600,1700,1800],2:[1500,2000,1400,1500,2000],
3:[2000,2000,2000,2000,2000],51:[65,80,75,80,75],52:[63,82,85,85,75],53:[83,80,75,76,78]})
test_df
1 2 3 51 52 53
0 1600 1500 2000 65 63 83
1 1600 2000 2000 80 82 80
2 1600 1400 2000 75 85 75
3 1700 1500 2000 80 85 76
4 1800 2000 2000 75 75 78
def calc_mean_based_on_conditions(row):
list_of_columns_to_average = []
for i in range(1,4):
if row[i] < 1700:
list_of_columns_to_average.append(i+50)
if not list_of_columns_to_average:
return np.nan
else:
return row[(list_of_columns_to_average)].mean(axis=1)
test_df['MeanValue'] = test_df.apply(calc_mean_based_on_conditions, axis=1)
我删除了我的另一个答案,因为它走错了路。您要做的是生成条件列的掩码,然后使用该掩码将函数应用于其他列。本例中1对应51,2对应52等
import pandas as pd
import numpy as np
test_df = pd.DataFrame({1:[1600,1600,1600,1700,1800],2:[1500,2000,1400,1500,2000],
3:[2000,2000,2000,2000,2000],51:[65,80,75,80,75],52:[63,82,85,85,75],53:[83,80,75,76,78]})
test_df
1 2 3 51 52 53
0 1600 1500 2000 65 63 83
1 1600 2000 2000 80 82 80
2 1600 1400 2000 75 85 75
3 1700 1500 2000 80 85 76
4 1800 2000 2000 75 75 78
# create dictionary to map columns to one another
l1=list(range(1,4))
l2=list(range(50,54))
d = {k:v for k,v in zip(l1,l2)}
d
{1: 51, 2: 52, 3: 53}
temp=test_df[l1] > 1700 # Subset initial dataframe, generate mask
for _, row in temp.iterrows(): #iterate through subsetted data
list_of_columns_for_mean=list() # list of columns for later computation
for k, v in d.items(): #iterate through each k:v and evaluate conditional for each row
if row[k]:
list_of_columns_for_mean.append(v)
# the rest should be pretty easy to figure out
这不是一个优雅的解决方案,但它是一个解决方案。不幸的是,我 运行 没有时间专注于此,但希望这能让您指明更好的方向。
可能有更好的矢量化方法来执行此操作,但您可以在没有函数
的情况下执行此操作import numpy as np
import pandas as pd
from collections import defaultdict
test_df = pd.DataFrame({1:[1600,1600,1600,1700,1800],2:[1500,2000,1400,1500,2000],
3:[2000,2000,2000,2000,2000],51:[65,80,75,80,75],52:[63,82,85,85,75],53:[83,80,75,76,78]})
# List of columns that you're applying the condition to
condition_cols = list(range(1,4))
# Get row and column indices where this condition is true
condition = np.where(test_df[condition_cols].lt(1700))
# make a dictionary mapping row to true columns
cond_map = defaultdict(list)
for r,c in zip(*condition):
cond_map[r].append(c)
# Get the means of true columns
means = []
for row in range(len(test_df)):
if row in cond_map:
temp = []
for col in cond_map[row]:
# Needs 51 because of Python indexing starting at zero + 50
temp.append(test_df.loc[row, col+51])
means.append(temp)
else:
# If the row has no true columns (i.e row 4)
means.append(np.nan)
test_df['Means'] = [np.mean(l) for l in means]
问题是以矢量化方式索引真实行 和 列。
一些非常相关的东西(支持 int 作为列名)- https://github.com/theislab/anndata/issues/31
由于这个 bug/issue,我将列名转换为字符串类型:
test_df = pd.DataFrame({'1':[1600,1600,1600,1700,1800],'2':[1500,2000,1400,1500,2000],
'3':[2000,2000,2000,2000,2000],'51':[65,80,75,80,75],'52':[63,82,85,85,75],'53':
[83,80,75,76,78]})
创建了一个新数据框 - new_df 以满足要求
new_df = test_df[['1', '2', '3']].where(test_df[['1','2','3']]<1700).notnull()
new_df 现在看起来像这样
1 2 3
0 True True False
1 True False False
2 True True False
3 False True False
4 False False False
然后只需重命名该列并使用 'where'
进行检查new_df = new_df.rename(columns={"1": "51", "2":"52", "3":"53"})
test_df['mean_value'] = test_df[['51', '52', '53']].where(new_df).mean(axis=1)
这应该会给你想要的输出 -
1 2 3 51 52 53 mean_value
0 1600 1500 2000 65 63 83 64.0
1 1600 2000 2000 80 82 80 80.0
2 1600 1400 2000 75 85 75 80.0
3 1700 1500 2000 80 85 76 85.0
4 1800 2000 2000 75 75 78 NaN