我有一个大数据框,这里只是示例数据:
length force d1 d2 d3 d4
1 5000 300 300 300 300
1.2 5000 300 300 300 300
1.4 5000 300 300 300 300
1.6 2000 500 300 100 300
1.8 2000 600 300 200 300
2 3500 500 300 300 300
2.2 3500 300 300 300 300
2.4 3500 100 300 300 300
2.5 1500 100 400 200 300
2.6 1500 200 300 200 300
3 6000 200 200 200 100
我有四个参数– d1, d2, d3 and d4
。我想遍历它们并找到行和(row-1)之间的区别。对于两个参数,这种差异至少应在一行中出现(不能更大,可以更小)。我以为可以在数据框d1_test, d2_test, d3_test, d4_test
中添加新列,如下所示:
df['d1_test'] = df['d1'].diff() != 0
所以我会得到:
length force d1 d2 d3 d4 d1_test d2_test d3_test 4_test
1 5000 300 300 300 300 False False False False
1.2 5000 300 300 300 300 False False False False
1.4 5000 300 300 300 300 False False False False
1.6 2000 500 300 100 300 True False True False
1.8 2000 600 300 200 300 True False True False
2 3500 500 300 300 300 True False True False
2.2 3500 300 300 300 300 True False False False
2.4 3500 100 300 300 300 True False False False
2.5 1500 100 400 200 300 False True True False
2.6 1500 200 300 200 300 True True False False
3 6000 200 200 400 100 False True False True
让我们考虑每个参数(d1, d2, d3, d4)
也代表一个固定值:d1_pos = 30, d2_pos = 40, d3_pos=60, d4_pos=90.
然后是我无法弄清的部分。我想添加一个新列(带有计算),例如df['result']
,当d1-d4_test中的两个为真时,它会查找。我可以使用布尔值sum()做到这一点,所以当sum==2
时,我不知道哪个两个参数为True。
在df['result']
中,我想要这样的东西:
if d1_test AND d2_test = True:
df['force'] / (d2_pos - d1_pos)
elif d1_test AND d3_test = True:
df['force'] / (d3_pos - d1_pos)
elif d1_test AND d4_test = True:
df['force'] / (d4_pos - d1_pos)
并类似地用于所有其他组合。我认为这不是正确的方法,因为我最终遇到了许多组合。如果更改了许多参数,例如,如果我添加d5, d6, d7
,这也需要很多工作。
预期结果:
length force d1 d2 d3 d4 d1_test d2_test d3_test 4_test result
1 5000 300 300 300 300 FALSE FALSE FALSE FALSE NaN
1.2 5000 300 300 300 300 FALSE FALSE FALSE FALSE NaN
1.4 5000 300 300 300 300 FALSE FALSE FALSE FALSE NaN
1.6 2000 500 300 100 300 TRUE FALSE TRUE FALSE 66.66666667
1.8 2000 600 300 200 300 TRUE FALSE TRUE FALSE 66.66666667
2 3500 500 300 300 300 TRUE FALSE TRUE FALSE 116.7
2.2 3500 300 300 300 300 TRUE FALSE FALSE FALSE Nan
2.4 3500 100 300 300 300 TRUE FALSE FALSE FALSE NaN
2.5 1500 100 400 200 300 FALSE TRUE TRUE FALSE 75
2.6 1500 200 300 200 300 TRUE TRUE FALSE FALSE 150
3 6000 200 200 400 100 FALSE TRUE FALSE TRUE 120
我也尝试使用groupby()
并对数据进行切片,但无法真正弄清楚。我确定有更好的解决方案吗?
我希望这是可以理解的。
非常感谢。
答案 0 :(得分:1)
您可以创建布尔掩码,然后使用apply()
将自定义计算应用于其余的非零列:
values = {'d1': 30, 'd2': 40, 'd3': 60, 'd4': 90}
mask = df[['d1','d2','d3','d4']].diff().fillna(0).ne(0)
def calc(x):
vals = df[mask].iloc[x.name].dropna().index.tolist()
if len(vals)<2: return None
return x['force']/abs(values[vals[0]]-values[vals[1]])
df['result'] = np.where(mask.sum(axis=1)==2, df.apply(calc, axis=1), np.nan)
返回:
length force d1 d2 d3 d4 result
0 1.0 5000 300 300 300 300 NaN
1 1.2 5000 300 300 300 300 NaN
2 1.4 5000 300 300 300 300 NaN
3 1.6 2000 500 300 100 300 66.666667
4 1.8 2000 600 300 200 300 66.666667
5 2.0 3500 500 300 300 300 116.666667
6 2.2 3500 300 300 300 300 NaN
7 2.4 3500 100 300 300 300 NaN
8 2.5 1500 100 400 200 300 75.000000
9 2.6 1500 200 300 200 300 150.000000
10 3.0 6000 200 200 200 100 120.000000
答案 1 :(得分:1)
只要您在某处拥有di
的列表,只要您查找只有2个True
的行,该方法就可以用于任意数量的di_pos
列
list_pos = [30, 40, 60, 90] # [d1_pos ,d2_pos ...
# Use `filter`, `diff` and `values` to get all the values of the columns di_test at once
arr_bool = (df.filter(like='d').diff() !=0).values
#create a mask where the sum in each row is equal to 2
mask = arr_bool.sum(1) == 2
#get the values in the rows using the list list_pos and the mask
arr_val = list_pos *arr_bool[mask]
#create the column result using
df.loc[mask,'result'] = df.loc[mask,'force']/(arr_val[arr_val .nonzero()][1::2] -
arr_val [arr_val .nonzero()][0::2])
print (df)
length force d1 d2 d3 d4 result
0 1.0 5000 300 300 300 300 NaN
1 1.2 5000 300 300 300 300 NaN
2 1.4 5000 300 300 300 300 NaN
3 1.6 2000 500 300 100 300 66.666667
4 1.8 2000 600 300 200 300 66.666667
5 2.0 3500 500 300 300 300 116.666667
6 2.2 3500 300 300 300 300 NaN
7 2.4 3500 100 300 300 300 NaN
8 2.5 1500 100 400 200 300 75.000000
9 2.6 1500 200 300 200 300 150.000000
10 3.0 6000 200 200 200 100 120.000000