Добавление столбца в массив numpy на основе if / then данных в массиве - PullRequest
1 голос
/ 28 января 2020

У меня есть многомерный массив numpy, например, так:

np.array([("a",1,"x"),("b",2,"y"),("c",1,"z")])

Мне нужно создать четвертый «столбец» в массиве, например, на основе if of of 2nd столбца.

Если [:,2] == 1, тогда newcolumn = 'Wow' иначе 'Dud'

Так что он возвращает что-то вроде:

[("a",1,"x","Wow"),("b",2,"y","Dud"),("c",1,"z","Wow")]

Поскольку я собираюсь обрабатывать около 100 миллионов строк данных имеют решающее значение.

Заранее спасибо за любую помощь.

Ответы [ 3 ]

1 голос
/ 28 января 2020

Обратите внимание, что dtype должен содержать самые длинные строки, которые он когда-либо будет содержать, в этом случае, длиной 3

  a = np.array([("a",1,"x"),("b",2,"y"),("c",1,"z")], dtype='<U3')
a
array([['a', '1', 'x'],
       ['b', '2', 'y'],
       ['c', '1', 'z']], dtype='<U1')

Создайте массив заполнителей впереди, для скорость. Обратите внимание, что типом является строка, но вы можете оставить ее пустой, я не уверен, как это повлияет на скорость. Было бы лучше использовать только один и тот же тип в вашем массиве и не иметь numpy удерживать нечисловые c типы.

> b = np.new_arr = np.empty((a.shape[0], a.shape[1] + 1), dtype=a.dtype)

Назначить a первым столбцам

> b[:, :a.shape[1]] = a

опросить соответствующий столбец для соответствующего условия

> cond_indices = a[:, 1] == '1'

назначить по маске

>b[cond_indices, a.shape[1]] = "Wow"
>b[~cond_indices, a.shape[1]] = "Dud"

наслаждайся

b
array([['a', '1', 'x', 'Wow'],
       ['b', '2', 'y', 'Dud'],
       ['c', '1', 'z', 'Wow']], dtype='<U3')
1 голос
/ 28 января 2020

Попробуйте pandas

>> import pandas as pd
>> df = pd.DataFrame([("a",1,"x"),("b",2,"y"),("c",1,"z")], columns=['col1', 'col2', 'col3'])
df
  col1  col2 col3
0    a     1    x
1    b     2    y
2    c     1    z

создайте функцию для работы со строками (не обязательно лямбда) и используйте apply для axis=1 (строки). Это даст вам новый столбец.

>> b = lambda row: "Wow" if row['col2'] == 1 else "Dud" 
>> new_col = df.apply(b, axis=1)
new_col
0    Wow
1    Dud
2    Wow
dtype: object

добавьте новый столбец в фрейм данных.

>> df['new_col'] = new_col
df
  col1  col2 col3 new_col
0    a     1    x     Wow
1    b     2    y     Dud
2    c     1    z     Wow

и преобразовать обратно в список кортежей

tuples = [tuple(x) for x in df[['col1','col2','col3','new_col']].to_numpy()]
[('a', 1, 'x', 'Wow'), ('b', 2, 'y', 'Dud'), ('c', 1, 'z', 'Wow')]

Предложение: не используйте списки кортежей. Используйте данные кадры. Не говоря уже о больших данных.

0 голосов
/ 28 января 2020

Ваш конструктор массива создает строку dtype:

In [73]: arr = np.array([("a",1,"x"),("b",2,"y"),("c",1,"z")])                                   
In [74]: arr                                                                                     
Out[74]: 
array([['a', '1', 'x'],
       ['b', '2', 'y'],
       ['c', '1', 'z']], dtype='<U1')

2-й столбец?

In [75]: arr[:,2]                                                                                
Out[75]: array(['x', 'y', 'z'], dtype='<U1')
In [76]: arr[:,1]                                                                                
Out[76]: array(['1', '2', '1'], dtype='<U1')

go для проверки по строке:

In [77]: arr[:,1]=="1"                                                                           
Out[77]: array([ True, False,  True])

Создайте новый массив с нужными строками:

In [78]: np.where(arr[:,1]=="1", "Wow","Dud")                                                    
Out[78]: array(['Wow', 'Dud', 'Wow'], dtype='<U3')

присоедините его к оригиналу создайте новый массив (это не на месте):

In [79]: np.column_stack((arr, Out[78]))                                                         
Out[79]: 
array([['a', '1', 'x', 'Wow'],
       ['b', '2', 'y', 'Dud'],
       ['c', '1', 'z', 'Wow']], dtype='<U3')

, но с pandas

In [80]: df = pd.DataFrame([("a",1,"x"),("b",2,"y"),("c",1,"z")], columns=['col1', 'col2', 'col3'
    ...: ])                                                                                      
In [81]: df                                                                                      
Out[81]: 
  col1  col2 col3
0    a     1    x
1    b     2    y
2    c     1    z
In [82]: df["newcol"] = np.where(df["col2"]==1, "Wow","Dud")                                     
In [83]: df                                                                                      
Out[83]: 
  col1  col2 col3 newcol
0    a     1    x    Wow
1    b     2    y    Dud
2    c     1    z    Wow

pandas хранит свои данные в массивах, по одному на каждый кадр данных или по одному на серию (столбец). Переключение на numpy автоматически не ускоряет процесс. Итерация строки в массиве так же медленна, как и строка apply в кадре данных. Но, как я показываю здесь, операция с целым массивом часто может применяться ко всему фрейму данных. А добавить столбец в фрейм данных проще, чем добавить столбец в массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...