Почему мой новый столбец назначается net после использования метода .sample? - PullRequest
4 голосов
/ 28 марта 2019

Итак, я просто отвечал на вопрос и наткнулся на что-то интересное:

Фрейм данных выглядит следующим образом:

  string1 string2
0     abc     def
1     ghi     jkl
2     mno     pqr
3     stu     vwx

Поэтому, когда я делаю следующее, назначение новых столбцов работает:

df['string3'] = df.string2

print(df)

  string1 string2 string3
0     abc     def     def
1     ghi     jkl     jkl
2     mno     pqr     pqr
3     stu     vwx     vwx

Но когда я использую pandas.DataFrame.Series.sample, новый столбец получает net, по крайней мере, не sampled one:

df['string4'] = df.string2.sample(len(df.string2))
print(df)
  string1 string2 string3 string4
0     abc     def     def     def
1     ghi     jkl     jkl     jkl
2     mno     pqr     pqr     pqr
3     stu     vwx     vwx     vwx

Итак, я проверил некоторые вещи:

Test1 Использование образца без присваивания дает нам правильный вывод:

df.string2.sample(len(df.string2))

2    pqr
1    jkl
0    def
3    vwx
Name: string2, dtype: object

Test2 Перезаписать тоже нельзя:

df['string2'] = df.string2.sample(len(df.string2))
print(df)
  string1 string2
0     abc     def
1     ghi     jkl
2     mno     pqr
3     stu     vwx

Это работает но почему?

df['string2'] = df.string2.sample(len(df.string2)).values
print(df)
  string1 string2
0     abc     jkl
1     ghi     def
2     mno     vwx
3     stu     pqr

Почему мне нужно явно использовать .values или .tolist(), чтобы получить правильное назначение?

Ответы [ 2 ]

4 голосов
/ 28 марта 2019

pandas чувствителен к index, что означает, что они проверяют index, когда assign это, то есть когда вы назначаете serise, весь df не изменяется, так как index не измените, после sort_index, он все равно покажет тот же порядок values, но если вы сделаете присвоение numpy array, index не будет учитываться, так что само значение будет присвоено обратно оригинал df, который дает выход

Пример egde

df['string3']=pd.Series(['aaa','aaa','aaa','aaa'],index=[100,111,112,113])
df
Out[462]: 
  string1 string2 string3
0     abc     vwx     NaN
1     ghi     jkl     NaN
2     mno     dfe     NaN
3     stu     pqr     NaN

Из-за этого индекса чувствительны, когда вы выполняете назначение условия с помощью .loc

Вы всегда можете сделать

df.loc[df.condition,'value']=df.value*100 
# since the not selected one will not be change 

То же самое, что вы делаете с np.where

df['value']=np.where(df.condition,df.value*100 ,df.value)

Некоторые другие варианты использования когда я делаю groupby apply с функцией non-agg и пытаюсь присвоить его обратно, почему это не удалось

df['String4']=df.groupby('string1').apply(lambda x :x['string2']+'aa')

TypeError: несовместимый индекс вставленного столбца с индексом кадра

Давайте попробуем взглянуть на возвращение groupby.apply

df.groupby('string1').apply(lambda x : x['string2']+'aa')
Out[466]: 
string1   
abc      0    vwxaa
ghi      1    jklaa
mno      2    dfeaa
stu      3    pqraa
Name: string2, dtype

Обратите внимание, что здесь добавляется еще один уровень в индекс, так что возвращаемое значение - это индекс с несколькими индексами, и исходный df имеет только одно измерение, которое вызовет сообщение об ошибке.


Как это исправить?


reset index и используя исходный индекс, который является вторым уровнем продукта groupby, затем присвойте его обратно

df['String4']=df.groupby('string1').apply(lambda x : x['string2']+'aa').reset_index(level=0,drop=True)
df
Out[469]: 
  string1 string2 string3 String4
0     abc     vwx     NaN   vwxaa
1     ghi     jkl     NaN   jklaa
2     mno     dfe     NaN   dfeaa
3     stu     pqr     NaN   pqraa

Как отметил Эрфан в комментарии, как мы можем запретить случайно назначить нежелательное значение для pandas.DataFrame

Два разных способа назначения.

1-й, с массивом, списком или кортежом. НЕ МОЖЕТ ВЫРАВНИВАТЬ, что означает, что если у вас есть разная длина между df и назначить объект, это не удастся

2-е назначение с pandas object, ВСЕГДА выравнивает, ошибки не вернется, даже длина отличается

Однако, когда объект назначения имеет дублирующийся индекс, возникает ошибка

df['string3']=pd.Series(['aaa','aaa','aaa','aaa'],index=[100,100,100,100])
ValueError: cannot reindex from a duplicate axis
3 голосов
/ 28 марта 2019

Это потому, что индекс все тот же, попробуйте с reset_index:

df.string2=df.string2.sample(len(df.string2)).reset_index(drop=True)
print(df)

  string1 string2
0     abc     jkl
1     ghi     pqr
2     mno     vwx
3     stu     vwx

С другой стороны, .values имеет только значения без индекса, поэтому работает

...