大熊猫元素比较和创造选择

时间:2016-05-24 07:07:24

标签: python pandas list-comprehension

在数据框中,我想将列的元素与值进行比较,并将通过比较的元素排序到新列中。

df = pandas.DataFrame([{'A':3,'B':10},
                       {'A':2, 'B':30},
                       {'A':1,'B':20},
                       {'A':2,'B':15},
                       {'A':2,'B':100}])

df['C'] = [x for x in df['B'] if x > 18]

我无法找出错误和原因:

  

ValueError:值的长度与索引的长度

不匹配

3 个答案:

答案 0 :(得分:3)

我认为您可以loc使用boolean indexing

print (df)
   A    B
0  3   10
1  2   30
2  1   20
3  2   15
4  2  100

print (df['B'] > 18)
0    False
1     True
2     True
3    False
4     True
Name: B, dtype: bool

df.loc[df['B'] > 18, 'C'] = df['B']
print (df)
   A    B      C
0  3   10    NaN
1  2   30   30.0
2  1   20   20.0
3  2   15    NaN
4  2  100  100.0

如果您需要按条件选择boolean indexing

print (df[df['B'] > 18])
   A    B
1  2   30
2  1   20
4  2  100

如果需要更快的速度,请使用where

df['C'] = df.B.where(df['B'] > 18)

计时len(df)=50k):

In [1367]: %timeit (a(df))
The slowest run took 8.34 times longer than the fastest. This could mean that an intermediate result is being cached.
1000 loops, best of 3: 1.14 ms per loop

In [1368]: %timeit (b(df1))
100 loops, best of 3: 15.5 ms per loop

In [1369]: %timeit (c(df2))
100 loops, best of 3: 2.93 ms per loop

时间安排的代码

import pandas as pd

df = pd.DataFrame([{'A':3,'B':10},
                       {'A':2, 'B':30},
                       {'A':1,'B':20},
                       {'A':2,'B':15},
                       {'A':2,'B':100}])
print (df)
df = pd.concat([df]*10000).reset_index(drop=True)
df1 = df.copy()
df2 = df.copy()

def a(df):
    df['C'] = df.B.where(df['B'] > 18)
    return df

def b(df1):    
    df['C'] = ([x if x > 18 else None for x in df['B']])
    return df

def c(df2):    
    df.loc[df['B'] > 18, 'C'] = df['B']
    return df

print (a(df))
print (b(df1))
print (c(df2))

答案 1 :(得分:2)

正如Darren所提到的,DataFrame中的所有列应该具有相同的长度。

当您尝试print [x for x in df['B'] if x > 18]时,您只能获得[30, 20, 100]个值。但是你有五个索引/行。这就是你得到Length of values does not match length of index错误的原因。

您可以按如下方式更改代码:

df['C'] = [x if x > 18 else None for x in df['B']]
print df

你会得到:

   A    B      C
0  3   10    NaN
1  2   30   30.0
2  1   20   20.0
3  2   15    NaN
4  2  100  100.0

答案 2 :(得分:0)

DataFrame中的所有列必须具有相同的长度。因为您要过滤掉一些值,所以您尝试在列C中插入的值少于在列A和B中插入的值。

因此,您的两个选项是为C开始一个新的DataFrame:

dfC = [x for x in df['B'] if x > 18]

或者当x不是18+时列中的一些虚拟值。 E.g:

df['C'] = np.where(df['B'] > 18, True, False)

甚至:

df['C'] = np.where(df['B'] > 18, 'Yay', 'Nay')

P.S。另请参阅:Pandas conditional creation of a series/dataframe column了解其他方法。