Как объединить одноименное имя в одно имя на основе идентификатора, а сложение и вычитание на основе кода - PullRequest
1 голос
/ 21 мая 2019

Я новичок, пожалуйста, не ставьте мне минус балл

У меня есть такой фрейм данных

    Month   Name       id   Info   d/k Ex/Im    Income
0   Jan    Alice sal  212  charge  k   export     100
1   Jan    sal Alice  212  charge  k   export      10
2   Jan    Bob        567  charge  k   export     200
3   Feb    Alice sal  212  charge  k   export     100
4   Jan    Bob        567  cost    k   import      75
5   jan    Bob        567  charge  D   export      50

В этом случае

Я хочу объединить имена 'alice sal' и 'sal alice' (прочитайте имя первой строки), чтобы получить одно имя, потому что у них обоих одинаковый идентификатор. В данном случае "Алиса Сал"

Тогда я хочу сделать условное заявление на основе "дебет (d (-)) / кредит (k (+))", если есть имя с индикатором "D" Так что в этом случае "bob = 200-50 = 150".

Ожидаемое

       Month      Feb      Jan
       Ex/Im      export  export      import
       Info        charge charge       cost 
ID.    Name
212    Alice sal     100    110           0
567    Bob             0    150          75

Что мне делать? Это мой последний код

df.pivot_table(index="Name", columns=["Month", "Ex/Im", "Info"], values="Income", aggfunc='sum', fill_value=0)

спасибо за @ ch33hau за вашу помощь, ответ

    # 1. Negate the values of `Income` when `D` is found, 
#    you can write your own method and use `df.apply` 
#    to make it idempotent if you prefer.
df.loc[df['d/k'] == 'D', 'Income'] = -df[df['d/k'] == 'D']['Income']

# 2. Group by
gdf = df.groupby(['id', 'Month', 'Ex/Im', 'Info']).agg({'Income':'sum', 'Name':'first'})

# 3. Lastly apply `pivot_table` which is quite similar to what you have wrote. 
gdf.pivot_table(
    index=["id", "Name"], 
    columns=["Month", "Ex/Im", "Info"], 
    values=["Name", "Income"], 
    aggfunc='sum', 
    fill_value=0)

работает, но сравнение не удалось. Это сообщение «futurewarning: поэлементное сравнение = сбой; вместо этого возвращается скаляр, но в будущем будет выполнено поэлементное сравнение (result = method (y))

я дам более подробную информацию

        Month   Name       id   Info   d/k Ex/Im    Income
0        Jan    Alice sal  212  charge  K   export     100
1        Jan    Alice sal  212  charge  K   export      10
2        Jan    sal alice  212  charge  D   export     100
2        Jan    Alice sal  212  charge  D   export     100
4        Jan    Alice sal  212  cost    K   export     200
5        Jan    sal alice  212  cost    D   export      10
6        Jan    sal alice  212  cost    D   export      20
7        Feb    Alice sal  212  charge  k   export     100

на основе идентификатора результат будет

                  Income
  Month           Feb         Jan
  Ex/Im           export      export    import
  Info            charge      charge    cost
  id    Name            
  212   Alice sal 100         -90       170

примечание: в моем фрейме данных не только Алиса Сал имеет похожее имя.

1 Ответ

1 голос
/ 21 мая 2019
# Preparing data
# Note that I have clean up the `jan` to `Jan` and `Charge` to `charge`
data = [{'Month': 'Jan', 'Name': 'Alice sal', 'id': 212, 'Info': 'charge', 'd/k': 'k', 'Ex/Im': 'export', 'Income': 100.15},
{'Month': 'Jan', 'Name': 'sal Alice', 'id': 212, 'Info': 'charge', 'd/k': 'k', 'Ex/Im': 'export', 'Income': 10},
{'Month': 'Jan', 'Name': 'Bob', 'id': 567, 'Info': 'charge', 'd/k': 'k', 'Ex/Im': 'export', 'Income': 200},
{'Month': 'Feb', 'Name': 'Alice sal', 'id': 212, 'Info': 'charge', 'd/k': 'k', 'Ex/Im': 'export', 'Income': 100},
{'Month': 'Jan', 'Name': 'Bob', 'id': 567, 'Info': 'cost', 'd/k': 'k', 'Ex/Im': 'import', 'Income': 75},
{'Month': 'Jan', 'Name': 'Bob', 'id': 567, 'Info': 'charge', 'd/k': 'D', 'Ex/Im': 'export', 'Income': 50}]

df = pd.DataFrame(data)
# Clean up name by ID
# Create a dataframe to store names depends on whichever found first.
df_name = df.groupby('id').first()[['Name']]

def cleanup_name(row, df_name):
    return df_name.at[row['id'], 'Name']

# `apply` is useful in applying complex logic, but it comes with some performance cost.
df['Name'] = df.apply(lambda x: cleanup_name(x, df_name), axis=1)
# 1. Negate the values of `Income` when `D` is found, 
#    you can write your own method and use `df.apply` 
#    to make it idempotent if you prefer.
df.loc[df['d/k'] == 'D', 'Income'] = -df[df['d/k'] == 'D']['Income']

# 2. Group by
gdf = df.groupby(['id', 'Month', 'Ex/Im', 'Info']).agg({'Income':'sum', 'Name':'first'})

# 3. Lastly apply `pivot_table` which is quite similar to what you have wrote. 
gdf.pivot_table(
    index=["id", "Name"], 
    columns=["Month", "Ex/Im", "Info"], 
    values=["Name", "Income"], 
    aggfunc='sum', 
    fill_value=0)


# Result:
#                 Income
# Month           Feb         Jan
# Ex/Im           export      export    import
# Info            charge      charge    cost
# id    Name            
# 212   Alice sal 100         110       0
# 567   Bob       0           150       75

Но сначала нужно очистить данные, есть один jan в Month, где остальные начинаются с заглавной буквы. То же самое для Info, начинаются с заглавной буквы.

Обновление:

После очистки имени все написанное до этого работает хорошо для меня, по данным ниже:

data = [
    {'Month': 'Jan', 'Name': 'Alice sal', 'id': 212, 'Info': 'charge', 'd/k': 'K', 'Ex/Im': 'export', 'Income': 100},
    {'Month': 'Jan', 'Name': 'Alice sal', 'id': 212, 'Info': 'charge', 'd/k': 'K', 'Ex/Im': 'export', 'Income': 10},
    {'Month': 'Jan', 'Name': 'Alice sal', 'id': 212, 'Info': 'charge', 'd/k': 'D', 'Ex/Im': 'export', 'Income': 100},
    {'Month': 'Jan', 'Name': 'Alice sal', 'id': 212, 'Info': 'charge', 'd/k': 'D', 'Ex/Im': 'export', 'Income': 100},
    {'Month': 'Jan', 'Name': 'Alice sal', 'id': 212, 'Info': 'cost', 'd/k': 'K', 'Ex/Im': 'export', 'Income': 200},
    {'Month': 'Jan', 'Name': 'Alice sal', 'id': 212, 'Info': 'cost', 'd/k': 'D', 'Ex/Im': 'export', 'Income': 10},
    {'Month': 'Jan', 'Name': 'Alice sal', 'id': 212, 'Info': 'cost', 'd/k': 'D', 'Ex/Im': 'export', 'Income': 20},
    {'Month': 'Feb', 'Name': 'Alice sal', 'id': 212, 'Info': 'charge', 'd/k': 'K', 'Ex/Im': 'export', 'Income': 100}]

df = pd.DataFrame(data)

Было бы здорово, если вы подготовите этот код для генерации данных в следующий раз, когда вы зададите вопрос, это сократит время, чтобы получить правильный ответ =)

...