Как определить изменение строки в строке по сравнению с предыдущей строкой в ​​кадре данных? - PullRequest
2 голосов
/ 07 апреля 2020

У меня есть DataFrame из pandas:

import pandas as pd
inp = [{'Name': 'John', 'Year':2018, 'Address':'Beverly hills'}, {'Name': 'John', 'Year':2018, 'Address':'Beverly hills'}, {'Name': 'John', 'Year':2019, 'Address':'Beverly hills'}, {'Name': 'John', 'Year':2019, 'Address':'Orange county'}, {'Name': 'John', 'Year':2019, 'Address':'New York'}, {'Name': 'Steve', 'Year':2018, 'Address':'Canada'}, {'Name': 'Steve', 'Year':2019, 'Address':'Canada'}, {'Name': 'Steve', 'Year':2019, 'Address':'Canada'}, {'Name': 'Steve', 'Year':2020, 'Address':'California'}, {'Name': 'Steve', 'Year':2020, 'Address':'Canada'}]
df = pd.DataFrame(inp)
print (df)

Если по сравнению с предыдущей строкой происходит изменение строкового значения строки, я хочу идентифицировать его в отдельной строке "Cng-Address" ", и если значение строки numberri c изменится, укажите его в столбце" Cng-Year ". Если нет изменений, определите его как ноль.

Индекс - «Имя», означающее, что вышеуказанные вычисления должны быть выполнены для всех строк, связанных с именем человека. Если «Имя» меняется (например, от Джона к Стиву), тогда вычисления для «Cng-Address» и «Cng-Year» должны быть сброшены. Год столбца отсортирован по возрастанию.

В качестве окончательного отчета я хочу получить:

  • Джон изменил время года «1» и изменил местоположение «2» раза
  • Стив измененные годы «2» раза и места смены «2» раза
  • Общее количество измененных адресов за 2019 год - «2» раза

Текущий выход:

+-------+------+---------------+
| Name  | Year | Address       |
+-------+------+---------------+
| John  | 2018 | Beverly hills |
+-------+------+---------------+
| John  | 2018 | Beverly hills |
+-------+------+---------------+
| John  | 2019 | Beverly hills |
+-------+------+---------------+
| John  | 2019 | Orange county |
+-------+------+---------------+
| John  | 2019 | New York      |
+-------+------+---------------+
| Steve | 2018 | Canada        |
+-------+------+---------------+
| Steve | 2019 | Canada        |
+-------+------+---------------+
| Steve | 2019 | Canada        |
+-------+------+---------------+
| Steve | 2020 | California    |
+-------+------+---------------+
| Steve | 2020 | Canada        |
+-------+------+---------------+

Идеальный выход:

+-------+------+---------------+----------+-------------+
| Name  | Year | Address       | Cng-Year | Cng-Address |
+-------+------+---------------+----------+-------------+
| John  | 2018 | Beverly hills | 0        | 0           |
+-------+------+---------------+----------+-------------+
| John  | 2018 | Beverly hills | 0        | 0           |
+-------+------+---------------+----------+-------------+
| John  | 2019 | Beverly hills | 1        | 0           |
+-------+------+---------------+----------+-------------+
| John  | 2019 | Orange county | 0        | 1           |
+-------+------+---------------+----------+-------------+
| John  | 2019 | New York      | 0        | 1           |
+-------+------+---------------+----------+-------------+
| Steve | 2018 | Canada        | 0        | 0           |
+-------+------+---------------+----------+-------------+
| Steve | 2019 | Canada        | 1        | 0           |
+-------+------+---------------+----------+-------------+
| Steve | 2019 | Canada        | 0        | 0           |
+-------+------+---------------+----------+-------------+
| Steve | 2020 | California    | 1        | 1           |
+-------+------+---------------+----------+-------------+
| Steve | 2020 | Canada        | 0        | 1           |
+-------+------+---------------+----------+-------------+

Ответы [ 3 ]

3 голосов
/ 08 апреля 2020

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

df["Cng-Year"] = ((df["Year"] != df["Year"].shift(1)) & (df["Name"] == df["Name"].shift())).astype(int)
df["Cng-Address"] = ((df["Address"] != df["Address"].shift(1)) & (df["Name"] == df["Name"].shift())).astype(int)
#df[['Cng-Year','Cng-Address']]=df[['Cng-Year','Cng-Address']].replace(True,1).replace(False,0) OR
#df[['Cng-Year','Cng-Address']] = np.where(df[['Cng-Year','Cng-Address']], 1,0)
2 голосов
/ 08 апреля 2020

Вы можете сделать с groupby:

groups = df.groupby('Name')

for col in ['Year', 'Address']:
    df[f'cng-{col}'] = groups[col].shift().fillna(df[col]).ne(df[col]).astype(int)

Выход:

    Name  Year        Address  cng-Year  cng-Address
0   John  2018  Beverly hills         0            0
1   John  2018  Beverly hills         0            0
2   John  2019  Beverly hills         1            0
3   John  2019  Orange county         0            1
4   John  2019       New York         0            1
5  Steve  2018         Canada         0            0
6  Steve  2019         Canada         1            0
7  Steve  2019         Canada         0            0
8  Steve  2020     California         1            1
9  Steve  2020         Canada         0            1
1 голос
/ 08 апреля 2020

Вы можете использовать прокрутку и проверить, равно ли значение указанному выше:

df['Cng-Year'] = df.groupby('Name')['Year'].transform(lambda x: x.rolling(2).agg(lambda x: x.iloc[0]!=x.iloc[1]).fillna(0))
df['Cng-Address'] = df.groupby('Name')['Address'].transform(lambda x: x.rolling(2).agg(lambda x: x.iloc[0]!=x.iloc[1]).fillna(0))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...