用数据框对应元素的列表函数替换列中某行的值
我有一个用户定义的函数(叫做 f),它是一个列表的函数。比如说,这个函数可以是计算列表中所有元素的和,但也可以是其他的函数。
接下来,我有一个数据表(dataframe),里面有两列:'pred' 列包含了一些数字的列表,而 'value' 列则包含一个单独的数字。这里的 -1 是一个占位符,需要被更新。
import pandas as pd
def f(my_list):
return sum(my_list)
data = {'pred':[[],[1],[1],[1],[2],[2,3],[2,4],[3],[3,4],[4],[6,7,9,10]]}
df = pd.DataFrame(data)
df.index = df.index + 1
df.loc[5,'value'] = 1
df.loc[8,'value'] = 0
df.loc[10,'value'] = 2
df.loc[11,'value'] = 100
df.value = df.value.fillna(-1).astype(int) #placeholder, the values cannot be negative
print(df)
pred value
1 [] -1
2 [1] -1
3 [1] -1
4 [1] -1
5 [2] 1
6 [2, 3] -1
7 [2, 4] -1
8 [3] 0
9 [3, 4] -1
10 [4] 2
11 [6, 7, 9, 10] 100
现在,我需要反向遍历这个数据表的每一行,把 -1 的值更新为那些在 'pred' 列中包含当前行的 'i' 的值的列表应用函数 f 后的结果。可以保证,在第 1 行到第 i 行的 'pred' 列中不会出现 'i'。
在这个例子中,我们应该得到:
value in row 9: f([100]) = 100;
value in row 7: f([100]) = 100;
value in row 6: f([100]) = 100;
value in row 4: f([2, 100, 100]) = 202;
value in row 3: f([100, 0, 100]) = 200;
value in row 2: f([1, 100, 100]) = 201;
value in row 1: f([201, 200, 202]) = 603.
所以,我需要帮助来写一个循环来完成这个任务。
for i in range(len(df),0,-1):
if df.loc[i,'value'] == -1:
df.loc[i,'value'] = ???
任何建议都非常感谢。
1 个回答
2
如果我理解正确,你可以创建一个字典,这个字典里存的是被其他索引引用的索引。然后你可以反向遍历那些-1的索引,并根据这些索引找到相关的行,然后把这些行传递给f
函数:
s = df['pred'].explode()
dic = s.index.groupby(s)
# {1: [2, 3, 4], 2: [5, 6, 7], 3: [6, 8, 9], ...}
for i in df.index[df['value'].eq(-1)][::-1]:
df.loc[i, 'value'] = f(df.loc[dic.get(i, []), 'value'])
更新后的数据表:
pred value
1 [] 603
2 [1] 201
3 [1] 200
4 [1] 202
5 [2] 1
6 [2, 3] 100
7 [2, 4] 100
8 [3] 0
9 [3, 4] 100
10 [4] 2
11 [6, 7, 9, 10] 100
接下来,我们一步一步分析这个循环,它的作用是:
df.loc[9, 'value'] = f(df.loc[[11], 'value']) # f([100])
df.loc[7, 'value'] = f(df.loc[[11], 'value']) # f([100])
df.loc[6, 'value'] = f(df.loc[[11], 'value']) # f([100])
df.loc[4, 'value'] = f(df.loc[[7, 9, 10], 'value']) # f([100, 100, 2])
df.loc[3, 'value'] = f(df.loc[[6, 8, 9], 'value']) # f([100, 0, 100])
df.loc[2, 'value'] = f(df.loc[[5, 6, 7], 'value']) # f([1, 100, 100])
df.loc[1, 'value'] = f(df.loc[[2, 3, 4], 'value']) # f([201, 200, 202])