сгруппировать по + случай, когда в другой колонке с пандами - PullRequest
0 голосов
/ 29 января 2019

У меня есть модель данных с тремя столбцами (CUST_ID, TOPIC, VALUE)

data = pd.DataFrame({"CUST_ID":["C1", "C1", "C2", "C3", "C3"],
                       "TOPIC":["TOPIC1", "TOPIC2", "TOPIC2", "TOPIC1", "TOPIC2"],
                       "VALUE":[10, 15, 8, 5, 20]})

Я хочу сгруппировать по CUST_ID, преобразовать столбец "TOPIC" в два столбца "TOPIC_a_VALUE" и "TOPIC_b_VALUE"

Я знаю, как сделать это с помощью SQL, но как это сделать с помощью панд?

SELECT CUST_ID,
       MAX(CASE WHEN TOPIC = "TOPIC1" THEN VALUE ELSE 0 END) AS TOPIC_a_VALUE
       MAX(CASE WHEN TOPIC = "TOPIC2" THEN VALUE ELSE 0 END) AS TOPIC_b_VALUE
FROM TABLE
GROUP BY CUST_ID

Результат, который я хочу получить ниже,

result = pd.DataFrame({"CUST_ID":["C1", "C2", "C3"],
                       "TOPIC_a_VALUE":[10, np.nan, 5],
                       "TOPIC_b_VALUE":[15, 8, 20]})

Ответы [ 4 ]

0 голосов
/ 29 января 2019

Вы можете использовать groupby следующим образом:

df=data.pivot_table(index=['CUST_ID','TOPIC'],columns=['TOPIC']).reset_index()
df.columns=[''.join(col) for col in df.columns.values]

df1 = df.groupby('CUST_ID').ffill()\
        .groupby('CUST_ID').last()\
        .reset_index()

Для очистки кадра данных

df1 = df1.drop(columns = ['TOPIC']).
rename(columns{'VALUETOPIC1':'TOPIC_a_VALUE','VALUETOPIC2':'TOPIC_b_VALUE'})
0 голосов
/ 29 января 2019

IIUC вам нужно что-то вроде:

df=data.pivot_table(index=['CUST_ID','TOPIC'],columns=['TOPIC']).reset_index()
df.columns=[''.join(col) for col in df.columns.values]
df.loc[df.CUST_ID.duplicated(keep=False)]=df.loc[df.CUST_ID.duplicated(keep=False)].bfill()
df=df.drop_duplicates('CUST_ID')
df=df.drop([col for col in df.columns if 'Key' in col],axis=1).reset_index(drop=True)

print(df)

  CUST_ID   TOPIC  VALUETOPIC1  VALUETOPIC2
0      C1  TOPIC1         10.0         15.0
1      C2  TOPIC2          NaN          8.0
2      C3  TOPIC1          5.0         20.0
0 голосов
/ 29 января 2019

Возможно, более читабельный, чем другие предлагаемые ответы, я бы сказал:

data.groupby(['CUST_ID', 'TOPIC'])['VALUE'].max().unstack()
# Output
#TOPIC   TOPIC1 TOPIC2
#CUST_ID              
#C1        10.0   15.0
#C2         NaN    8.0
#C3         5.0   20.0

Если вы предпочитаете, вы, конечно, можете переименовать столбцы:

.rename(columns={'TOPIC1': 'TOPIC_a_VALUE', 'TOPIC2': 'TOPIC_b_VALUE'})
0 голосов
/ 29 января 2019

Ваш запрос не имеет смысла в SQL.Я предполагаю, что вы намереваетесь что-то вроде этого:

SELECT CUST_ID,
       MAX(CASE WHEN TOPIC = 'a' THEN VALUE ELSE 0 END) AS TOPIC_a_VALUE
       MAX(CASE WHEN TOPIC = 'b' THEN VALUE ELSE 0 END) AS TOPIC_b_VALUE
FROM TABLE
GROUP BY CUST_ID;

Это не поможет напрямую с решением Pandas, но, по крайней мере, запрос будет иметь смысл.

...