Установить значение первого элемента в фрагменте в python pandas
Итак, я хотел бы сделать фрагмент кадра данных, а затем установить значение первого элемента в этом фрагменте без копирования фрейма данных. Например:
df = pandas.DataFrame(numpy.random.rand(3,1))
df[df[0]>0][0] = 0
Этот фрагмент не имеет значения и только для примера и снова вернет весь фрейм данных. Точка, делая это, как в примере, вы получаете настройку с предупреждением об ошибке (понятно). Я также попробовал срез сначала, а затем использовал ILOC/IX/LOC и дважды использовал ILOC, то есть что-то вроде:
df.iloc[df[0]>0,:][0] = 0
df[df[0]>0,:].iloc[0] = 0
И ни одна из этих работ не работает. Опять же - я не хочу делать копию фрейма данных, даже если он имеет идентификатор только нарезанной версии.
EDIT:
Кажется, есть два способа, используя маску или IdxMax. Метод IdxMax работает, если ваш индекс уникален, а метод маски - нет. В моем случае индекс не уникален, о чем я забыл упомянуть в начальном посте.
Ответы
Ответ 1
Таким образом, используя некоторые ответы, мне удалось найти способ одного лайнера для этого:
np.random.seed(1)
df = pd.DataFrame(np.random.randint(4, size=(5,1)))
print df
0
0 1
1 3
2 0
3 0
4 3
df.loc[(df[0] == 0).cumsum()==1,0] = 1
0
0 1
1 3
2 1
3 0
4 3
По сути, это использование маски внутри с концом.
Ответ 2
Я думаю, вы можете использовать idxmax
для получения индекса первого значения True
, а затем установить loc
:
np.random.seed(1)
df = pd.DataFrame(np.random.randint(4, size=(5,1)))
print (df)
0
0 1
1 3
2 0
3 0
4 3
print ((df[0] == 0).idxmax())
2
df.loc[(df[0] == 0).idxmax(), 0] = 100
print (df)
0
0 1
1 3
2 100
3 0
4 3
df.loc[(df[0] == 3).idxmax(), 0] = 200
print (df)
0
0 1
1 200
2 0
3 0
4 3
EDIT:
Решение с уникальным индексом:
np.random.seed(1)
df = pd.DataFrame(np.random.randint(4, size=(5,1)), index=[1,2,2,3,4])
print (df)
0
1 1
2 3
2 0
3 0
4 3
df = df.reset_index()
df.loc[(df[0] == 3).idxmax(), 0] = 200
df = df.set_index('index')
df.index.name = None
print (df)
0
1 1
2 200
2 0
3 0
4 3
EDIT1:
Решение с MultiIndex
:
np.random.seed(1)
df = pd.DataFrame(np.random.randint(4, size=(5,1)), index=[1,2,2,3,4])
print (df)
0
1 1
2 3
2 0
3 0
4 3
df.index = [np.arange(len(df.index)), df.index]
print (df)
0
0 1 1
1 2 3
2 2 0
3 3 0
4 4 3
df.loc[(df[0] == 3).idxmax(), 0] = 200
df = df.reset_index(level=0, drop=True)
print (df)
0
1 1
2 200
2 0
3 0
4 3
EDIT2:
Решение с двойным cumsum
:
np.random.seed(1)
df = pd.DataFrame([4,0,4,7,4], index=[1,2,2,3,4])
print (df)
0
1 4
2 0
2 4
3 7
4 4
mask = (df[0] == 0).cumsum().cumsum()
print (mask)
1 0
2 1
2 2
3 3
4 4
Name: 0, dtype: int32
df.loc[mask == 1, 0] = 200
print (df)
0
1 4
2 200
2 4
3 7
4 4
Ответ 3
Рассмотрим блок данных df
df = pd.DataFrame(dict(A=[1, 2, 3, 4, 5]))
print(df)
A
0 1
1 2
2 3
3 4
4 5
Создайте произвольный фрагмент slc
slc = df[df.A > 2]
print(slc)
A
2 3
3 4
4 5
Доступ к первой строке slc
внутри df
с помощью index[0]
и loc
df.loc[slc.index[0]] = 0
print(df)
A
0 1
1 2
2 0
3 4
4 5
Ответ 4
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(6,1),index=[1,2,2,3,3,3])
df[1] = 0
df.columns=['a','b']
df['b'][df['a']>=0.5]=1
df=df.sort(['b','a'],ascending=[0,1])
df.loc[df[df['b']==0].index.tolist()[0],'a']=0
В этом методе дополнительная копия dataframe не создается, но вводится дополнительный столбец, который можно отбросить после обработки. Чтобы выбрать любой индекс, а не первый, вы можете изменить последнюю строку следующим образом
df.loc[df[df['b']==0].index.tolist()[n],'a']=0
чтобы изменить любой n-й элемент в срезе
DF
a
1 0.111089
2 0.255633
2 0.332682
3 0.434527
3 0.730548
3 0.844724
df после нарезки и маркировки их
a b
1 0.111089 0
2 0.255633 0
2 0.332682 0
3 0.434527 0
3 0.730548 1
3 0.844724 1
После изменения значения первого элемента в срезе (с пометкой 0) до 0
a b
3 0.730548 1
3 0.844724 1
1 0.000000 0
2 0.255633 0
2 0.332682 0
3 0.434527 0