2014-09-05 6 views
1

У меня есть большой dataframe с данными индивидуального уровня в четырех столбцах: идентификационный номер человека, ее год, возраст и состояние ее перемещения. Я использую groupby на идентификационном номере человека, хранящемся в столбце unique_pid2.Python pandas: заменить выбранные значения в объекте groupby

import pandas as pd 

gr_data = pd.read_csv("M:/test.csv").groupby('unique_pid2') 

group = gr_data.get_group('5904_181') 

print group 

Каждая группа выглядит следующим образом:

 unique_pid2 year age moved 
798908 5904_181 1983 0  0 
798909 5904_181 1984 0  0 
798910 5904_181 1985 0  0 
798911 5904_181 1986 0  0 
798912 5904_181 1987 2  5 
798913 5904_181 1988 0  5 
798914 5904_181 1989 0  0 
798915 5904_181 1990 0  0 
798916 5904_181 1991 0  0 
798917 5904_181 1992 0  0 
798918 5904_181 1993 0  0 
798928 5904_181 2009 24  5 
798929 5904_181 2011 26  1 

Для каждой группы, я хочу, чтобы заполнить значения, которые равны нулю в обоих moved и age столбцов с альтернативными значениями, но только если эти наблюдения «зажаты» между другими наблюдениями с по меньшей мере одним ненулевым значением в столбцах и moved.

Например, в приведенной выше группе, я хочу, чтобы заполнить линии 798914: 798918, но не 798908:798911 .. Для наблюдений, которые имеют как age и moved значение, равное 0, я написал функцию, которая заменяет нули соответственно , Но я хочу вызвать эту функцию в случаях «сэндвич», таких как 798914: 798918, и не знаю, как получить доступ к этим строкам.

До сих пор я пытался что-то вроде:

group.loc[(group["age"] == 0) & (group["moved"] == 0), ['age', 'moved']] = someFunction(group) 

Но это заполняет не-зажатые наблюдения, как первые четыре строки в указанной выше группе. Как следует использовать функцию для заполнения значений age и moved, равных 0 в каждой группе, но только для наблюдений, которые зажаты между наблюдениями с ненулевыми значениями в age, moved или обоих?

+1

Вы можете просто выбрать индекс подгруппы группы, которая имеет все нулевые строки? Затем найдите, где первый набор 0s разбивается с использованием логической лямбда (это индекс теперь = 1 + индекс до?). Затем используйте функцию ur в подмножестве строк после первого перерыва в 0, но до следующего набора нулей. Имеет ли это смысл? Там может быть более умный способ. – robertevansanders

ответ

1

Предполагая, что значения в age и moved неотрицательны, можно выбрать нужные строки с помощью cumsum:

mask = ((grp['age'].cumsum()>0) & (grp['moved'].cumsum()>0) 
     & (grp['age'] == 0) & (grp['moved'] == 0)) 

, поскольку, когда накопленная сумма больше 0, должно быть, было предшествующее положительное значение ,

Например,

import pandas as pd 

df = pd.read_csv("M:/test.csv") 
gr_data = df.groupby('unique_pid2') 
def foo(grp): 
    mask = ((grp['age'].cumsum()>0) & (grp['moved'].cumsum()>0) 
      & (grp['age'] == 0) & (grp['moved'] == 0)) 
    grp.loc[mask, ['age', 'moved']] = 'foo' 
    return grp 
df = gr_data.apply(foo) 
print(df) 

дает

unique_pid2 year age moved 
0  5904_181 1983 0  0 
1  5904_181 1984 0  0 
2  5904_181 1985 0  0 
3  5904_181 1986 0  0 
4  5904_181 1987 2  5 
5  5904_181 1988 0  5 
6  5904_181 1989 foo foo 
7  5904_181 1990 foo foo 
8  5904_181 1991 foo foo 
9  5904_181 1992 foo foo 
10 5904_181 1993 foo foo 
11 5904_181 2009 24  5 
12 5904_181 2011 26  1 
Смежные вопросы