2015-04-21 2 views
12

Я работаю с пандами и у меня есть кадр данных, где мы можем иметь одно из трех значений заселены:Объединить значение столбцов фрейма данных панд в новый столбец

ID_1 ID_2 ID_3 
abc  NaN  NaN 
NaN  def  NaN 
NaN  NaN  ghi 
NaN  NaN  jkl 
NaN  mno  NaN 
pqr  NaN  NaN 

И моя цель состоит в том, чтобы объединить эти три колонок в новые столбцы в моем кадре данных:

ID_1 ID_2 ID_3 Combined_ID 
abc  NaN  NaN abc 
NaN  def  NaN def 
NaN  NaN  ghi ghi 
NaN  NaN  jkl jkl 
NaN  mno  NaN mno 
pqr  NaN  NaN pqr 

в идеале было бы просто найти то, что существует не нулевое значение в столбцах 1 через 3, но я мог бы также сцеплять, так как мы должны иметь только один из трех заселенных для каждой строки , Благодарю.

df_note = pd.read_csv("NoteIds.csv") 
df_note['Combined_ID'] = # ID_1 + ID_2 + ID_3 
+1

Мы уверены, что в строке есть только одно значение, отличное от NaN? – DSM

+0

@EdChum - На самом деле есть и другие столбцы. Так что да, только один не NaN, но только для этих трех столбцов, а не для всей строки. – EMC

ответ

3

Предположим, что может быть более одного значения, отличного от NaN, для каждой строки. Тем не менее это должно сработать.

In [43]: df['Combined_ID'] = df.apply(
       lambda x : ''.join([e for e in x if isinstance(e, basestring)]), 
         axis=1) 

Для каждой строки извлекайте строковые элементы и присоединяйтесь к ним.

In [44]: df 
Out[44]: 
    ID_1 ID_2 ID_3 Combined_ID 
0 abc NaN NaN   abc 
1 NaN def NaN   def 
2 NaN NaN ghi   ghi 
3 NaN NaN jkl   jkl 
4 NaN mno NaN   mno 
5 pqr NaN NaN   pqr 

Мне понравился ответ @ EdChum и выглядит более читаемым.

Интересно, что метод fillna('').sum(axis=1) является дорогостоящим для данных меньшего размера.

In [45]: %timeit df.fillna('').sum(axis=1) 
1000 loops, best of 3: 808 µs per loop 

In [46]: %timeit df.apply(lambda x : ''.join([e for e in x if isinstance(e, basestring)]), axis=1) 
1000 loops, best of 3: 285 µs per loop 

Ибо ['ID_1','ID_2','ID_3'] колонны только

df[['ID_1','ID_2','ID_3']].apply(lambda_function) 
+0

Это не так удивительно, но «apply» не масштабируется хорошо, я просто сделал тайминги на 600 строк df, а тайминги были 6.24ms против 33.3ms, сравнивая мой метод с вашим, я ожидаю, что разница в производительности значительно возрастет на гораздо большем datasets – EdChum

+0

Есть ли способ указать только 3 столбца, которые мне нужны? Это приводит к включению других не связанных столбцов. – EMC

+0

@EdChum Абсолютно, 'apply' не работает хорошо на больших наборах данных. Итак, я упомянул * дорогой для этих меньших данных. * =) – Zero

12

Вы можете использовать свойство, суммирующий будет конкатенации строковых значений, так что вы могли бы назвать fillna и передать пустой ул и вызов sum и передать параметров axis=1 для суммирования по строке:

In [26]: 

df['Combined_ID'] = df.fillna('').sum(axis=1) 
df 
Out[26]: 
    ID_1 ID_2 ID_3 Combined_ID 
0 abc NaN NaN   abc 
1 NaN def NaN   def 
2 NaN NaN ghi   ghi 
3 NaN NaN jkl   jkl 
4 NaN mno NaN   mno 
5 pqr NaN NaN   pqr 

Если вас интересуют только эти 3 столбца, вы можете просто выбрать их:

In [39]: 

df['Combined_ID'] = df[['ID_1','ID_2','ID_3']].fillna('').sum(axis=1) 
df 
Out[39]: 
    ID_1 ID_2 ID_3 Combined_ID 
0 abc NaN NaN   abc 
1 NaN def NaN   def 
2 NaN NaN ghi   ghi 
3 NaN NaN jkl   jkl 
4 NaN mno NaN   mno 
5 pqr NaN NaN   pqr 
+0

'df.max (axis = 1)' будет делать, не требуя 'fillna', я думаю. – piroot