pandas, найди и сохрани последовательные строки - создай панель данных - PullRequest
0 голосов
/ 14 октября 2018

У меня есть DataFrame, как показано ниже:

df = {'time': [1999,2001,2002,2003,2007,1999,2000,2001,2003,2004],
      'id':['A','A','A','A','A','B','B','B','B','B'],
      'value':[0.1,0.1,0.1,0.1,0.6,0.2,0.2,0.2,0.2,0.2]}
df = pd.DataFrame(df)

Я хочу создать из него набор данных панели на уровне id-time, что означает, что я хочу что-то вроде:

time id  value
0  2001  A    0.1
1  2002  A    0.1
2  2003  A    0.6
3  1999  B    0.2
4  2000  B    0.2
5  2001  B    0.2

Остались только последовательные строки каждого id, я могу закончить это всего несколькими строками в R,

df<-df %>% 
    mutate(time = as.integer(time)) %>% 
    group_by(gvkey, grp = cumsum(c(1, diff(time) != 1))) %>% 
    filter(n() >= consec_obs)
df<-df[,setdiff(colnames(df),c('grp'))]

, в которых consec_obs - это минимум последовательных строк, который нужно сохранить.

Я некоторое время искал, но не мог найти решение, которое меня немного удивило, так как это своего рода основные манипуляции эконометрического анализа, кто-нибудь знает, как это сделать с помощью Python?

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Надеюсь, это поможет вам.Я постараюсь объяснить каждую строку по мере продвижения вперед.

Импортируйте эти 2 пакета.

from itertools import groupby
import numpy as np

Ваш фрейм данных выглядит примерно так:

>>>df = {'time': [1999,2001,2002,2003,2007,1999,2000,2001,2003,2004],
  'id':['A','A','A','A','A','B','B','B','B','B'],
  'value':[0.1,0.1,0.1,0.1,0.6,0.2,0.2,0.2,0.2,0.2]}

>>>df = pd.DataFrame(df)
>>>df

    id  time    value
0   A   1999    0.1
1   A   2001    0.1
2   A   2002    0.1
3   A   2003    0.1
4   A   2007    0.6
5   B   1999    0.2
6   B   2000    0.2
7   B   2001    0.2
8   B   2003    0.2
9   B   2004    0.2

СначалаШаг: Найти уникальные идентификаторы.Вот как вы это делаете:

>>>unique = np.unique(df.id.values).tolist()
>>>unique
['A', 'B']

Второй шаг: для каждого идентификатора создайте список списков (я назвал его как группа).Каждый список во внешнем списке содержит последовательные числа.Чтобы прояснить ситуацию, я возьму отпечаток группы.Он сгруппирует список последовательных чисел.

Третий шаг: после группировки создайте фрейм данных только для тех значений, у которых длина группировки больше 2. (Я предполагаю 2, потому что вы не учитывалиB: 2003 и B: 2004 как последовательная последовательность.)

Вот как это работает:

# Create an Empty dataframe. This is where you will keep appending peices of dataframes
df2 = pd.DataFrame()
# Now you would want to iterate over your unique IDs ie. 'A', 'B'.
for i in unique:
#Create an empty list called Group. Here you will append lists that contain consecutive numbers.
    groups = []
    #Create a data frame where ID is equal to current iterating ID
    df1 = df.loc[df['id'] == i]
    #The next 2 for loops (nested) will return group (a list of lists)
    for key, group in groupby(enumerate(df1.time.values), lambda ix : ix[0] - ix[1]):
        list1 = []
        for j in list(group):
            list1.append(j[1])
        groups.append(list1)
    # See how your group for current ID looks
    print(groups)
    # Iterate within the created group. See if group length is > 2. If yes, append to df2 (the empty data frame that you created earlier)
    for j in groups:
        if len(j) > 1:
            # you are concatenating 2 frames in the below code.
            df2 = pd.concat([df2,df.loc[(df['time'].isin(j)) & (df['id'] == i)]])

Вуаля

>>>> df2
    id  time    value
1   A   2001    0.1
2   A   2002    0.1
3   A   2003    0.1
5   B   1999    0.2
6   B   2000    0.2
7   B   2001    0.2
0 голосов
/ 15 октября 2018

Имитируя решение R, в воскресенье вечером я придумаю версию на Python, вот она:

# lag where two rows within each group are not conesecutive
df['diff'] = df.groupby('id')['time'].diff()!=1
# cumulative summation
df['cusm'] = df.groupby('id')['diff'].cumsum()
# group by 'id' and 'cusm', then select those rows which satisfy prespecified condition
df.loc[df.groupby(['id','cusm']).transform('count')['diff'] >=3].drop(['diff','cusm'],axis=1)

Если это кажется трудным для понимания, попробуйте код в одну строку,вы доберетесь туда.

Возможно ли объединить первые две строки в одну?

...