迭代,选择和计算数据帧中的不同索引

时间:2018-11-30 17:44:48

标签: python pandas dataframe

我有一个大数据框,这里只是示例数据:

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()并对数据进行切片,但无法真正弄清楚。我确定有更好的解决方案吗?   我希望这是可以理解的。 非常感谢。

2 个答案:

答案 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