Панды создают строки на основе значений нескольких предыдущих столбцов для заданного количества предыдущих строк - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть фрейм данных, например:

A B  C
1 11 33
2 15 46 
3 12 91
1  8 75
3 35 63
2 22 52

Я создаю столбцы N, M и O на основе этих значений для предыдущих x строк:

  • N - число среди тех строк, где B> B этой строки, а C
  • M этой строки - число среди тех строк, в которых вышеприведенные условия не выполняются и A == 1
  • O - это число, для которого не выполняется ни одно из условий для N, а A! = 1

Первые x строкизатем упал.

(как следствие, N + M + 0 всегда == x )

Ожидаемый результат при x == 2:

A B  C  N M O
3 12 91 1 0 1  
1  8 75 0 1 1
3 35 63 2 0 0
2 22 52 2 0 0

Мое решение, так как я не смог придумать подход чистого панды, состоит в том, чтобы просто перебирать строки и использовать 3 разных счетчика:

    x=17 # "17" is not actually hardcoded, it's read from file
    for i, row in df.iterrows():
        n=0
        m=0
        o=0
        for j in range(1, x+1):
            if row.B > df.iloc[i-j].B and row.B < df.iloc[i-j].C:
                n+=1
            elif df.iloc[i-j].A == 1:
                m+=1
            else: 
                o+=1
        df.at[i,"N"] = n
        df.at[i,"M"] = m
        df.at[i,"O"] = o         
     df=df.iloc[x:]        

Это работает, но работаеточевидно, довольно медленный (df большой).Можно ли обойтись без итерации по строкам?Если да, то как?

1 Ответ

0 голосов
/ 23 ноября 2018

Мы можем получить его, используя merge и lambda, как показано ниже

df1 = df.merge(df.apply(lambda row: createMNO(row), axis=1), left_index=True, right_index=True)

, пожалуйста, найдите полный пример ниже.Нужно исправить логику сравнения, если мои представления о вашей логике неверны.

import pandas as pd

df = pd.DataFrame(columns=['A', 'B', 'C'])
df.loc[len(df)] = [1,11,33]
df.loc[len(df)] = [2,15,46]
df.loc[len(df)] = [3,12,91]
df.loc[len(df)] = [1,8,75]
df.loc[len(df)] = [3,35,63]
df.loc[len(df)] = [2,22,52]

x = 2 

def createMNO(row):
    subDF = df.loc[row.name - x :row.name - 1]
    n = len(subDF.loc[(subDF.B > row.B) & (subDF.C < row.C)])
    m = len(subDF.loc[~((subDF.B > row.B) & (subDF.C < row.C)) & (subDF.A == 1)])
    o = x - m - n
    return pd.Series({
        'N' : n,
        'M' : m,
        'O' : o
    })

df1 = df.merge(df.apply(lambda row: createMNO(row), axis=1), left_index=True, right_index=True)

print(df1.iloc[x:])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...