在python pandas

时间:2017-02-28 18:21:36

标签: python pandas slice mask argmax

所以我想制作一个数据帧切片然后设置该切片中第一个项的值而不复制数据帧。例如:

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

这些都不起作用。再次 - 我不想复制数据框,即使它只是切片版本。

编辑: 似乎有两种方法,使用掩码或IdxMax。如果索引是唯一的,IdxMax方法似乎有效,如果不是,则掩码方法。就我而言,索引并不是唯一的,我在最初的帖子中忘了提及。

4 个答案:

答案 0 :(得分:13)

我认为您可以使用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

编辑:

没有唯一索引的解决方案:

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

答案 1 :(得分:1)

考虑数据框CRYPT_VERIFYCONTEXT

int main()
{
    const char* passw = "password12";
    const char* toencrypt = "consectetur adipiscing elit. In tellus nisl,   sodales non arcu quis, sagittis maximus orci cras amet.";

    HCRYPTPROV hProv;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    DWORD todwSize = (DWORD)strlen(toencrypt), needSize;
    PBYTE pBuffer;

    if (CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
        {
            if (CryptHashData(hHash, (BYTE*)passw, (DWORD)strlen(passw), 0) &&
                CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
            {
                if (CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0))
                {
                    memcpy(pBuffer = (BYTE *)_alloca(needSize), toencrypt, todwSize);

                    if (CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize))
                    {
                        if (CryptDecrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize))
                        {
                            if (memcmp(pBuffer, toencrypt, strlen(toencrypt)))
                            {
                                __debugbreak();
                            }
                        }
                    }
                }
                CryptDestroyKey(hKey);
            }
            CryptDestroyHash(hHash);
        }
        CryptReleaseContext(hProv, 0);
    }

    return 0;
}

创建一些任意切片df

df = pd.DataFrame(dict(A=[1, 2, 3, 4, 5]))

print(df)

   A
0  1
1  2
2  3
3  4
4  5

使用slcslc = df[df.A > 2] print(slc) A 2 3 3 4 4 5

访问slcdf的第一行
index[0]

答案 2 :(得分:1)

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

在此方法中,不会创建数据帧的额外副本,但会引入一个额外的列,可以在处理后删除。要选择任何索引而不是第一个索引,您可以更改最后一行,如下所示

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

答案 3 :(得分:0)

因此,使用一些答案,我设法找到了一个单行方式来做到这一点:

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

基本上这是使用与cumsum内联的掩码。