У меня есть фрейм данных pandas, который мне нужно экспортировать в numpy для выполнения некоторых операций. Эти операции приводят к удалению некоторых столбцов. Я хотел бы сравнить полученный массив numpy с моим исходным фреймом данных, чтобы получить метки столбцов, которые были сохранены. Проблема в том, что некоторые столбцы могут быть не уникальными ...

Пример:

  1. Создайте образец фрейма данных:
>>> loci_df = pd.DataFrame(columns=['SNP1','SNP2','SNP3','SNP4','SNP5','SNP6','SNP7','SNP8','SNP9','SNP10'],
...                        data=[[ 0., np.NaN,  0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.],
...                                [ 0., np.NaN,  1.,  1.,  1.,  1.,  1.,  1.,  0.,  0.],
...                                [ np.NaN, np.NaN,  0.,  2.,  0.,  1.,  1.,  1.,  0., np.NaN],
...                                [ 0., np.NaN,  0.,  1.,  1.,  1.,  1.,  1.,  0.,  0.],
...                                [ 0., np.NaN,  2.,  1.,  0.,  1.,  1.,  1.,  0.,  0.],
...                                [ 0., np.NaN,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.],
...                                [ 0., np.NaN,  1.,  0.,  0.,  0.,  1.,  1.,  0.,  0.],
...                                [ 0., np.NaN,  0.,  0.,  0.,  1.,  1.,  1.,  0.,  0.],
...                                [ 0., np.NaN,  0.,  1.,  0.,  0.,  1.,  1.,  0.,  0.],
...                                [ 0., np.NaN,  0.,  1.,  1., np.NaN,  1.,  1.,  0.,  1.]])
>>> loci_df
   SNP1  SNP2  SNP3  SNP4  SNP5  SNP6  SNP7  SNP8  SNP9  SNP10
0   0.0   NaN   0.0   0.0   0.0   0.0   1.0   1.0   0.0    0.0
1   0.0   NaN   1.0   1.0   1.0   1.0   1.0   1.0   0.0    0.0
2   NaN   NaN   0.0   2.0   0.0   1.0   1.0   1.0   0.0    NaN
3   0.0   NaN   0.0   1.0   1.0   1.0   1.0   1.0   0.0    0.0
4   0.0   NaN   2.0   1.0   0.0   1.0   1.0   1.0   0.0    0.0
5   0.0   NaN   0.0   0.0   0.0   1.0   0.0   0.0   0.0    0.0
6   0.0   NaN   1.0   0.0   0.0   0.0   1.0   1.0   0.0    0.0
7   0.0   NaN   0.0   0.0   0.0   1.0   1.0   1.0   0.0    0.0
8   0.0   NaN   0.0   1.0   0.0   0.0   1.0   1.0   0.0    0.0
9   0.0   NaN   0.0   1.0   1.0   NaN   1.0   1.0   0.0    1.0

  1. Переместите его в массив numpy и выполните некоторые операции - здесь удалите столбцы, в которых все значения отсутствуют или все не пропущенные значения равны.
>>> loci = np.array(loci_df)
>>> m1 = np.isnan(loci)
>>> m2 = loci[0]==loci
>>> loci = loci[:,~(m1|m2).all(0)]
>>> loci
array([[ 0.,  0.,  0.,  0.,  1.,  1.,  0.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  0.],
       [ 0.,  2.,  0.,  1.,  1.,  1., nan],
       [ 0.,  1.,  1.,  1.,  1.,  1.,  0.],
       [ 2.,  1.,  0.,  1.,  1.,  1.,  0.],
       [ 0.,  0.,  0.,  1.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  0.,  1.,  1.,  0.],
       [ 0.,  0.,  0.,  1.,  1.,  1.,  0.],
       [ 0.,  1.,  0.,  0.,  1.,  1.,  0.],
       [ 0.,  1.,  1., nan,  1.,  1.,  1.]])

Теперь я хотел бы получить список меток в исходном фрейме данных, которые были сохранены после фильтрации в numpy.

['SNP3', 'SNP4', 'SNP5', 'SNP6', 'SNP7', 'SNP8', 'SNP10']

Примечание: некоторые столбцы могут быть не уникальными, например здесь столбцы SNP7 и SNP8 имеют одинаковые значения - я хочу сохранить их оба! Но это означает, что мой (не оптимальный) подход к использованию значений столбцов в качестве ключей словаря и меток столбцов в качестве значений словаря не сработает ...

Я пробовал считывать отфильтрованные данные в новый фрейм данных, а затем сравнивать оригинал с полученным, но неудивительно, что получаю KeyErrors:

>>> filtered=pd.DataFrame(data=loci)
>>> filtered
     0    1    2    3    4    5    6
0  0.0  0.0  0.0  0.0  1.0  1.0  0.0
1  1.0  1.0  1.0  1.0  1.0  1.0  0.0
2  0.0  2.0  0.0  1.0  1.0  1.0  NaN
3  0.0  1.0  1.0  1.0  1.0  1.0  0.0
4  2.0  1.0  0.0  1.0  1.0  1.0  0.0
5  0.0  0.0  0.0  1.0  0.0  0.0  0.0
6  1.0  0.0  0.0  0.0  1.0  1.0  0.0
7  0.0  0.0  0.0  1.0  1.0  1.0  0.0
8  0.0  1.0  0.0  0.0  1.0  1.0  0.0
9  0.0  1.0  1.0  NaN  1.0  1.0  1.0

loci_df.loc[:,np.all(loci_df.values==filtered.values, axis=0)]

Traceback (most recent call last):
  File "/Users/jilska2/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 2646, in get_loc
    return self._engine.get_loc(key)
  File "pandas/_libs/index.pyx", line 111, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/index.pyx", line 138, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/hashtable_class_helper.pxi", line 1618, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas/_libs/hashtable_class_helper.pxi", line 1626, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: False

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jilska2/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py", line 1761, in __getitem__
    return self._getitem_tuple(key)
  File "/Users/jilska2/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py", line 1271, in _getitem_tuple
    return self._getitem_lowerdim(tup)
  File "/Users/jilska2/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py", line 1388, in _getitem_lowerdim
    section = self._getitem_axis(key, axis=i)
  File "/Users/jilska2/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py", line 1964, in _getitem_axis
    return self._get_label(key, axis=axis)
  File "/Users/jilska2/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py", line 624, in _get_label
    return self.obj._xs(label, axis=axis)
  File "/Users/jilska2/opt/anaconda3/lib/python3.7/site-packages/pandas/core/generic.py", line 3529, in xs
    return self[key]
  File "/Users/jilska2/opt/anaconda3/lib/python3.7/site-packages/pandas/core/frame.py", line 2800, in __getitem__
    indexer = self.columns.get_loc(key)
  File "/Users/jilska2/opt/anaconda3/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 2648, in get_loc
    return self._engine.get_loc(self._maybe_cast_indexer(key))
  File "pandas/_libs/index.pyx", line 111, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/index.pyx", line 138, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/hashtable_class_helper.pxi", line 1618, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas/_libs/hashtable_class_helper.pxi", line 1626, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: False

Есть ли способ добиться этого или мне нужно полностью изменить свой подход?

1
branwen85 1 Дек 2020 в 14:10

1 ответ

Лучший ответ

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

loci = np.array(loci_df)
m1 = np.isnan(loci)
m2 = loci[0]==loci

mask = ~(m1|m2).all(0)
loci = loci[:,mask]

print (loci_df.columns[mask])
Index(['SNP3', 'SNP4', 'SNP5', 'SNP6', 'SNP7', 'SNP8', 'SNP10'], dtype='object')

filtered=pd.DataFrame(data=loci, columns=loci_df.columns[mask])
print (filtered)
   SNP3  SNP4  SNP5  SNP6  SNP7  SNP8  SNP10
0   0.0   0.0   0.0   0.0   1.0   1.0    0.0
1   1.0   1.0   1.0   1.0   1.0   1.0    0.0
2   0.0   2.0   0.0   1.0   1.0   1.0    NaN
3   0.0   1.0   1.0   1.0   1.0   1.0    0.0
4   2.0   1.0   0.0   1.0   1.0   1.0    0.0
5   0.0   0.0   0.0   1.0   0.0   0.0    0.0
6   1.0   0.0   0.0   0.0   1.0   1.0    0.0
7   0.0   0.0   0.0   1.0   1.0   1.0    0.0
8   0.0   1.0   0.0   0.0   1.0   1.0    0.0
9   0.0   1.0   1.0   NaN   1.0   1.0    1.0
0
jezrael 1 Дек 2020 в 11:13