[英]Pandas get postion of last value based on condition for each column (efficiently)
我想获取我的 dataframe 的每一列中值1
最后出现在哪一行的信息。鉴于最后一行索引,我想计算出现的“新近度”。 像这样:
>> df = pandas.DataFrame({"a":[0,0,1,0,0]," b":[1,1,1,1,1],"c":[1,0,0,0,1],"d":[0,0,0,0,0]})
>> df
a b c d
0 0 1 1 0
1 0 1 0 0
2 1 1 0 0
3 0 1 0 0
4 0 1 1 0
期望的结果:
>> calculate_recency_vector(df)
[3,1,1,None]
期望的结果显示每列“多少行之前”最后一次出现值1
。 例如,对于列a
,值1
最后出现在倒数第三行,因此结果向量中的新近度为3
。 任何想法如何实现这个?
编辑:为避免混淆,我将最后一列所需的 output 从0
更改为None
。 此列没有新近度,因为根本没有出现值1
。
编辑二:感谢您的精彩回答。 我必须在形状为 (42.250) 的数据帧上计算这个近因向量大约 150k 次。 更有效的解决方案将不胜感激。
更快更清洁的无环路解决方案:
>> def calculate_recency_for_one_column(column: pd.Series) -> int:
>> non_zero_values_of_col = column[column.astype(bool)]
>> if non_zero_values_of_col.empty:
>> return 0
>> return len(column) - non_zero_values_of_col.index[-1]
>> df = pd.DataFrame({"a":[0,0,1,0,0],"b":[1,1,1,1,1],"c":[1,0,0,0,1],"d":[0,0,0,0,0]})
>> df.apply(lambda column: calculate_recency_for_one_column(column),axis=0)
a 3
b 1
c 1
d 0
dtype: int64
旁注:使用pd.apply()
很慢(如此解释)。 存在更快的解决方案,例如使用np.where
或使用apply(...,raw=True)
。 有关详细信息,请参阅此问题。
使用此示例 dataframe,您可以定义一个 function,如下所示:
def calculate_recency_vector(df: pd.DataFrame, condition: int) -> list:
recency_vector = []
for col in df.columns:
last = 0
for i, y in enumerate(df[col].to_list()):
if y == condition:
last = i
recency = len(df[col].to_list()) - last
if recency == len(df[col].to_list()):
recency = None
recency_vector.append(recency)
return recency_vector
运行 function,它将返回:
calculate_recency_vector(df, 1)
[3, 1, 1, None]
实现此 function 的一种直接方法是使用循环遍历 DataFrame 中的每一列,并在该循环内使用另一个循环遍历列中的每一行。 对于每一行,检查值是否为 1。如果是,则更新变量以存储 len(df[column])-index。 内部循环完成后,返回存储的值作为该列的新近度。 如果 1 从未出现在列中,则返回 None。
import pandas
def calculate_recency_vector(df):
recency_vector = []
for column in df:
last_occurrence = None
for index, value in df[column].iteritems():
if value == 1:
last_occurrence =len(df[column])-index
recency_vector.append(last_occurrence)
return recency_vector
df = pandas.DataFrame({"a":[0,0,1,0,0]," b":[1,1,1,1,1],"c":[1,0,0,0,1],"d":[0,0,0,0,0]})
print(calculate_recency_vector(df))
这个
df = pandas.DataFrame({"a":[0,0,1,0,0]," b":[1,1,1,1,1],"c":[1,0,0,0,1],"d":[0,0,0,0,0]})
df.apply(lambda x : ([df.shape[0] - i for i ,v in x.items() if v==1] or [None])[-1], axis=0)
产生所需的 output 作为pd.Series
,唯一的区别是结果是 float 而None
被 pandas Nan
取代,然后你可以采用所需的列
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.