2017-01-11 2 views
1

У меня есть dataframe, который выглядит следующим образом:Значение по умолчанию для панд поиска, когда значение поиска не существует или равна нулю

 parent region 
estid    
1   NaN  A 
2   NaN  B 
3   1.0  A 
4   1.0  B 
5   2.0  C 
6   2.0  C 
7   8.0  A 

То, что я хочу, чтобы создать дополнительный столбец, содержащий region из parent, недобросовестный None, если родитель не найден в данных, например:

 parent region parent_region 
estid        
1   NaN  A   None 
2   NaN  B   None 
3   1.0  A    A 
4   1.0  B    A 
5   2.0  C    B 
6   2.0  C    B 
7   8.0  A   None 

следующие возвращает правильный результат:

df["parent_region"] = df.apply(lambda x : df.loc[x["parent"]]["region"] if not math.isnan(x["parent"]) and x["parent"] in df.index else None, axis = 1) 

Но я очень боюсь неэффективности, учитывая, что у моей DataFrame 168 миллионов строк. Есть ли лучший способ сделать это? Я посмотрел на и get, но я не могу понять, как работать с идентификаторами, которые могут быть NaN или нет в dataframe.

Например, я думал, что это может сработать: df.lookup(df["region"], df["parent"]), но он не любит очень много нулевых ключей. df.get("region") не возвращает область родителя, но сам столбец, поэтому он не делает то, что я хочу.

+1

Как 'map' выполнять? - 'df.parent.map (df.region)' –

+0

Чрезвычайно хорошо :-) В тесте на 100 тыс. строк карта занимает 0,02 секунды, а мое приложение занимает 16 секунд. С одной стороны, спасибо вам большое! С другой стороны, это раздражает, что решение было настолько простым, и я не думал об этом. Тоннельное видение, я думаю ... Поставьте его в качестве ответа, и я соглашусь с ним. – Mikk

ответ

2

Вы можете использовать метод Series.map, который функционирует аналогично словарю. Значения от parent column и регион столбец служат в качестве ключей и значений, составляющих его. Отображение происходит, если они имеют общий индекс между ними.

Кроме того, na_action=ignore может использоваться для ускорения этого процесса сопоставления, так как все NaNs, присутствующие в этих столбцах, будут полностью игнорироваться и просто распространяться.

И, наконец, недостающие значения должны быть заменены на None с использованием метода Series.replace.

df["parent_region"] = df.parent.map(df.region, na_action='ignore').replace({np.NaN:None}) 
Out[121]: 
estid 
1 None 
2 None 
3  A 
4  A 
5  B 
6  B 
7 None 
Name: parent_region, dtype: object 
1

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

z = pd.merge(x, x[['estid','region']],\ 
      left_on = 'parent',\ 
      right_on = 'estid',\ 
      how = 'left',\ 
      suffixes=('', '_parent')) #left join 

del z['estid_parent'] #remove uneeded row 

z['region_parent'] = z['region_parent'].replace({np.NaN:None}) #remove nans, same as other answer 
z 

    estid parent region region_parent 
0 1 NaN A None 
1 2 NaN B None 
2 3 1.0 A A 
3 4 1.0 B A 
4 5 2.0 C B 
5 6 2.0 C B 
6 7 8.0 A None 
+0

Очень круто, и на моем примере 100k он работает практически мгновенно, как «карта». Upvoted. – Mikk

Смежные вопросы