Pandas DataFrame: объединение объединяющихся объединений множества групп - PullRequest
0 голосов
/ 19 октября 2018

У меня есть DataFrame с DateTimeIndex, столбцом, по которому я хочу сгруппироваться, и столбцом, содержащим наборы целых чисел:

import pandas as pd

df = pd.DataFrame([['2018-01-01', 1, {1, 2, 3}],
                   ['2018-01-02', 1, {3}],
                   ['2018-01-03', 1, {3, 4, 5}],
                   ['2018-01-04', 1, {5, 6}],
                   ['2018-01-01', 2, {7}],
                   ['2018-01-02', 2, {8}],
                   ['2018-01-03', 2, {9}],
                   ['2018-01-04', 2, {10}]],
                  columns=['timestamp', 'group', 'ids'])

df['timestamp'] = pd.to_datetime(df['timestamp'])
df.set_index('timestamp', inplace=True)

            group        ids
timestamp                   
2018-01-01      1  {1, 2, 3}
2018-01-02      1        {3}
2018-01-03      1  {3, 4, 5}
2018-01-04      1     {5, 6}
2018-01-01      2        {7}
2018-01-02      2        {8}
2018-01-03      2        {9}
2018-01-04      2       {10}

Внутри каждой группы я хочу создать объединение скользящих множеств по последнему xдней.Таким образом, предполагая, что X = 3, результат должен быть:

            group              ids
timestamp                   
2018-01-01      1        {1, 2, 3}
2018-01-02      1        {1, 2, 3}
2018-01-03      1  {1, 2, 3, 4, 5}
2018-01-04      1     {3, 4, 5, 6}
2018-01-01      2              {7}
2018-01-02      2           {7, 8}
2018-01-03      2        {7, 8, 9}
2018-01-04      2       {8, 9, 10}

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

grouped = df.groupby('group')
new_df = pd.DataFrame()
for name, group in grouped:
    group['ids'] = [
        set.union(*group['ids'].to_frame().iloc(axis=1)[max(0, i-2): i+1,0])
        for i in range(len(group.index))
    ]
    new_df = new_df.append(group)

, которое дает правильный результат, но выглядит довольно неуклюже, а также выдает следующее предупреждение:

SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

Документация по предоставленной ссылке на самом деле не выглядитвпрочем, подходит к моей конкретной ситуации(По крайней мере, я не могу понять это в этом контексте.)

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

1 Ответ

0 голосов
/ 19 октября 2018

Как указано в документах , не используйте pd.DataFrame.append в цикле;Это будет дорого.

Вместо этого используйте list и укажите pd.concat.

Вы можете избежать SettingWithCopyWarning, создавая копии данных в вашемсписок, т. е. избегать цепного индексирования через assign + iloc в понимании списка:

L = [group.assign(ids=[set.union(*group.iloc[max(0, i-2): i+1, -1]) \
                       for i in range(len(group.index))]) \
     for _, group in df.groupby('group')]

res = pd.concat(L)

print(res)

            group              ids
timestamp                         
2018-01-01      1        {1, 2, 3}
2018-01-02      1        {1, 2, 3}
2018-01-03      1  {1, 2, 3, 4, 5}
2018-01-04      1     {3, 4, 5, 6}
2018-01-01      2              {7}
2018-01-02      2           {8, 7}
2018-01-03      2        {8, 9, 7}
2018-01-04      2       {8, 9, 10}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...