Исключить столбцы pandas dataframe на основе агрегированного количества его строк - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть следующий фрейм данных:

   Fruit                John      Mary        Paul     Anna
   Apples                1         1            1       5
   Oranges               2         2            2       3
   Lemons                1         1            4       1
   Berries               2         2            2       7

и у меня также есть следующие вложенные словари:

{Apples:{5:1,1:3},Oranges:{3:1,2:3},Lemons:{4:1,1:3},Berries:{7:1,2:3}}

, который говорит мне, что

  1. 1 человек имеет 5 яблок, а 3 человека - 1 яблоко
  2. 1 человек имеет 3 апельсина и 3 человека имеют 2 апельсина
  3. 1 человек имеет 4 лимона, а 3 человека - 1 лимон
  4. 1 человек имеет 7 ягод, а 3 человека имеют 2 ягоды

Теперь мне нужно извлечь людей, у которых есть либо 5 яблок, либо 3 апельсина, либо 4 лимона, либо 7 ягод, то есть все уникальные случаи в приведенном выше словаре.

Это означает, что, поскольку Мария, например, не приносит плода, исключается человек, но всегда находящийся в категории 3 одинаковых фигур.

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

Ожидаемый выход:

   Fruit           Paul     Anna
   Apples            2       5
   Oranges           2       3
   Lemons            4       1
   Berries           2       7

Ответы [ 3 ]

0 голосов
/ 14 сентября 2018

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

from io import StringIO

import pandas as pd


data = StringIO('''Fruit                John      Mary        Paul     Anna
Apples                1         1            1       5
Oranges               2         2            2       3
Lemons                1         1            4       1
Berries               2         2            2       7''')

df = pd.read_csv(data, sep='\s+').set_index('Fruit')

tr = df.transpose()
mask = ~pd.DataFrame({c: tr.duplicated(c, keep=False) for c in tr.columns}).all(axis=1)

df = df[mask.index[mask]]

Мыустановите индекс на 'Fruit' и затем транспонируйте, чтобы получить один столбец на 'Fruit' и одну строку на человека.Затем мы создаем маску, которая определяет, является ли значение в столбце дубликатом любых других, и проверяем, верно ли это во всех случаях.затем мы можем отфильтровать столбцы в нашем исходном кадре данных, используя эту маску.

Это дает нам следующее: df:

         Paul  Anna
Fruit              
Apples      1     5
Oranges     2     3
Lemons      4     1
Berries     2     7
0 голосов
/ 14 сентября 2018

Вы также можете использовать from_dict и isin

d = {'Apples':{5:1,1:3},'Oranges':{3:1,2:3},'Lemons':{4:1,1:3},'Berries':{7:1,2:3}}

. Преобразовать вышеуказанные клавиши DICT в df

# df1 = pd.DataFrame([[k for k in j.keys()] for i, j in d.items()])

df1 = pd.DataFrame(list(zip(*list(d.values())))).T

df[df.isin(df1[0])].dropna(how='all', axis=1).fillna(df).set_index(df.Fruit)

# Output:

         Paul   Anna
Fruit       
Apples   1.0    5.0
Oranges  2.0    3.0
Lemons   4.0    1.0
Berries  2.0    7.0
.
0 голосов
/ 14 сентября 2018

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

        John    Mary    Paul    Anna
Fruit               
Apples  3   1   2   5
Oranges 2   2   2   3
Lemons  1   1   4   1
Berries 2   2   2   7

df.set_index(['Fruit'],inplace=True)
column_names = df.apply(lambda x:x.name  if ((x.loc['Apples']==5) | (x.loc['Oranges']==3) | (x.loc['Lemons']==4) | (x.loc['Berries']==7)) else None)
df[list(filter(None,column_names))]

Из:

    Paul    Anna
Fruit       
Apples  2   5
Oranges 2   3
Lemons  4   1
Berries 2   7
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...