датафрейм iloc неожиданно работает в пандах - PullRequest
4 голосов
/ 10 мая 2019

Я создаю такой фрейм данных.

np.random.seed(2)
df=pd.DataFrame(np.random.randint(1,6,(6,6)))

out[]

0   1   1   4   3   4   1
1   3   2   4   3   5   5
2   5   4   5   3   4   4
3   3   2   3   5   4   1
4   5   4   2   3   1   5
5   5   3   5   3   2   1

разбиение кадра данных на 3,3 матрицы, как показано ниже, у него будет 16 матриц. ДФС = []

for col in range(df.shape[1]-2):
    for row in range(df.shape[0]-2):
        dfs.append(df.iloc[row:row+3,col:col+3])

позволяет печатать,

dfs[0]
1   1   4
3   2   4
5   4   5

dfs[1]
3   2   4
5   4   5
3   2   3
.
.
.
dfs[15]

5   4   1
3   1   5
3   2   1

написание функции для изменения значений из каждой матрицы в местоположениях [1,0] и [1,2] на ноль, так что мой вывод будет выглядеть так:

dfs[0]
1   1   4
0   2   0
5   4   5


def process(x):
    new=[]
    for d in x:
        d.iloc[1,0]=0
        d.iloc[1,2]=0
        new.append(d)
        print(d)
    return new

dfs=process(dfs.copy())

мой ожидаемый результат,

dfs[0]
1   1   4
0   2   0
5   4   5

но то, что возвращает моя функция,

dfs[0]
1   1   4
0   0   0
0   0   0

dfs[1]
0   0   0
0   0   0
0   0   0

Это производит больше нулей во всей матрице. Я не знаю, почему он работает неожиданно или что я делаю неправильно с моей функцией process, пожалуйста, помогите. Благодаря.

Ответы [ 2 ]

2 голосов
/ 10 мая 2019

Короче говоря, вы - жертва цепного индексирования , которое может привести к плохим событиям .

Когда вы нарезаете оригинал DataFrame,Вы получаете перекрывающиеся представления.

Изменение одного также изменяет другие, поскольку второй ряд одного чанка - это первый ряд другого, а третий ряд первого чанка - первый ряд еще одного, и так далее ... которыйВот почему вы видите ненулевые значения только на «ребрах», поскольку они уникальны для одного фрагмента.

Вы можете сделать копии каждого среза, например:

def process(x):
    new = []
    for d in x:
        d = d.copy()  # each one is now a copy
        d.iloc[1, 0]=0
        d.iloc[1, 2]=0
        new.append(d)
    return new

Наконец, обратите внимание, что dfs = process(dfs) на самом деле хорошо;вам не нужно делать копию прилагаемого list.

2 голосов
/ 10 мая 2019

Измените код и вызов функции process, чтобы получить требуемый вывод.Кроме того, я использовал цикл for для копирования для создания подмножества информационного кадра, который не зависит от изменений в будущем, в вашем случае он вносит изменения в исходный df, который отражается со всеми нулями в другом списке dfs:

for col in range(df.shape[1]-2):
    for row in range(df.shape[0]-2):
        dfs.append(df.iloc[row:row+3,col:col+3].copy())

dfs=process(dfs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...