Итерация, выбор и вычисление различных индексов в кадре данных - PullRequest
0 голосов
/ 30 ноября 2018

У меня большой массив данных, вот только примерные данные:

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 голосов
/ 30 ноября 2018

Этот метод может работать для любого количества столбцов 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
0 голосов
/ 30 ноября 2018

Вы можете создать логическую маску, а затем использовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...