Сводная таблица Pandas с использованием пользовательских условий на фрейме данных - PullRequest
0 голосов
/ 10 ноября 2018

Я хочу создать сводную таблицу на основе пользовательских условий в кадре данных:

Фрейм данных выглядит следующим образом:

>>> df = pd.DataFrame({"Area": ["A", "A", "B", "A", "C", "A", "D", "A"],
                       "City" : ["X", "Y", "Z", "P", "Q", "R", "S", "X"],
                       "Condition" : ["Good", "Bad", "Good", "Good", "Good", "Bad", "Good", "Good"], 
                       "Population" : [100,150,50,200,170,390,80,100]
                       "Pincode" : ["X1", "Y1", "Z1", "P1", "Q1", "R1", "S1", "X2"] })
>>> df
  Area City Condition   Population Pincode
 0    A    X      Good   100       X1
 1    A    Y       Bad   150       Y1
 2    B    Z      Good   50        Z1
 3    A    P      Good   200       P1
 4    C    Q      Good   170       Q1
 5    A    R       Bad   390       R1
 6    D    S      Good   80        S1
 7    A    X      Good   100       X2

Теперь я хочу повернуть фрейм данных df таким образом, чтобы я мог видеть уникальное количество городов для каждой области вместе с соответствующим количеством "хороших" городов, а также население области.

Я ожидаю такой вывод:

Area  city_count  good_city_count   Population
A        4        2                 940
B        1        1                 50
C        1        1                 170
D        1        1                 80
All      7        5                 1240

Я могу дать словарь для параметра aggfunc, но это не дает мне разбить количество городов между хорошими городами.

>>> city_count = df.pivot_table(index=["Area"],
                                values=["City", "Population"],
                                aggfunc={"City": lambda x: len(x.unique()),
                                         "Population": "sum"},
                                margins=True)

    Area    City    Population
0   A       4       940
1   B       1       50
2   C       1       170
3   D       1       80
4   All     7       1240

Я могу объединить две разные сводные таблицы - одну с количеством городов, а другую с населением, но это невозможно масштабировать для большого набора данных с большим aggfunc словарем.

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Другой метод без использования pivot_table. Используйте np.where с groupby + agg:

df['Condition'] = np.where(df['Condition']=='Good', df['City'], np.nan)
df = df.groupby('Area').agg({'City':'nunique', 'Condition':'nunique', 'Population':'sum'})\
                       .rename(columns={'City':'city_count', 'Condition':'good_city_count'})
df.loc['All',:] = df.sum()
df = df.astype(int).reset_index()

print(df)
  Area  city_count  good_city_count  Population
0    A           4                2         940
1    B           1                1          50
2    C           1                1         170
3    D           1                1          80
4  All           7                5        1240
0 голосов
/ 10 ноября 2018

Добавить новые параметры columns с fill_value, а также возможно использование nunique для функции агрегирования:

city_count = df.pivot_table(index = "Area", 
                            values = "City", 
                            columns='Condition', 
                            aggfunc = lambda x : x.nunique(), 
                            margins = True,
                            fill_value=0)
print (city_count)
Condition  Bad  Good  All
Area                     
A            2     2    4
B            0     1    1
C            0     1    1
D            0     1    1
All          2     5    7

Последнее, если необходимо преобразовать индекс в столбец и изменить имена столбцов:

city_count = city_count.add_suffix('_count').reset_index().rename_axis(None, 1)
print (city_count)
  Area  Bad_count  Good_count  All_count
0    A          2           2          4
1    B          0           1          1
2    C          0           1          1
3    D          0           1          1
4  All          2           5          7

EDIT:

d = {'City':'nunique','Population':'sum', 'good_city_count':'nunique'}
d1 = {'City':'city_count','Condition':'good_city_count'}

mask = df["Condition"] == 'Good'
df = (df.assign(good_city_count = lambda x: np.where(mask, x['City'], np.nan))
       .groupby('Area')
       .agg(d)
       .rename(columns=d1))

df = df.append(df.sum().rename('All')).reset_index()

print (df)
  Area  city_count  Population  good_city_count
0    A           4         940                2
1    B           1          50                1
2    C           1         170                1
3    D           1          80                1
4  All           7        1240                5
...