python用法 - pandas read_csv




根據熊貓中列中的值從DataFrame中選擇行 (8)

TL;博士

熊貓相當於

select * from table where column_name = some_value

table[table.column_name == some_value]

多種條件:

table((table.column_name == some_value) | (table.column_name2 == some_value2))

要么

table.query('column_name == some_value | column_name2 == some_value2')

代碼示例

import pandas as pd

# Create data set
d = {'foo':[100, 111, 222], 
     'bar':[333, 444, 555]}
df = pd.DataFrame(d)

# Full dataframe:
df

# Shows:
#    bar   foo 
# 0  333   100
# 1  444   111
# 2  555   222

# Output only the row(s) in df where foo is 222:
df[df.foo == 222]

# Shows:
#    bar  foo
# 2  555  222

在上面的代碼中,行df[df.foo == 222]給出了基於列值的行,在這種情況下為222

多種條件也是可能的:

df[(df.foo == 222) | (df.bar == 444)]
#    bar  foo
# 1  444  111
# 2  555  222

但在那一點上,我會建議使用query函數,因為它不那麼冗長,並且會得到相​​同的結果:

df.query('foo == 222 | bar == 444')

如何根據熊貓中某些列的值從DataFrame中選擇行?
在SQL中,我會使用:

select * from table where colume_name = some_value. 

我試圖看熊貓文檔,但沒有立即找到答案。


使用numpy.where可以實現更快的結果。

例如,使用unubtu的設置 -

In [76]: df.iloc[np.where(df.A.values=='foo')]
Out[76]: 
     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

時間比較:

In [68]: %timeit df.iloc[np.where(df.A.values=='foo')]  # fastest
1000 loops, best of 3: 380 µs per loop

In [69]: %timeit df.loc[df['A'] == 'foo']
1000 loops, best of 3: 745 µs per loop

In [71]: %timeit df.loc[df['A'].isin(['foo'])]
1000 loops, best of 3: 562 µs per loop

In [72]: %timeit df[df.A=='foo']
1000 loops, best of 3: 796 µs per loop

In [74]: %timeit df.query('(A=="foo")')  # slowest
1000 loops, best of 3: 1.71 ms per loop

對於pandas中的給定值,僅從多列中選擇特定列:

select col_name1, col_name2 from table where column_name = some_value.

選項:

df.loc[df['column_name'] == some_value][[col_name1, col_name2]]

要么

df.query['column_name' == "some_value"'][[col_name1, col_name2]]

我只是嘗試編輯這個,但我沒有登錄,所以我不知道我的編輯去了哪裡。 我試圖納入多個選擇。 所以我認為更好的答案是:

對於單個值來說,最直接的(人類可讀的)可能是:

df.loc[df['column_name'] == some_value]

對於您也可以使用的值列表:

df.loc[df['column_name'].isin(some_values)]

例如,

import pandas as pd
import numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
               'B': 'one one two three two two one three'.split(),
               'C': np.arange(8), 'D': np.arange(8) * 2})
print(df)
#      A      B  C   D
# 0  foo    one  0   0
# 1  bar    one  1   2
# 2  foo    two  2   4
# 3  bar  three  3   6
# 4  foo    two  4   8
# 5  bar    two  5  10
# 6  foo    one  6  12
# 7  foo  three  7  14

print(df.loc[df['A'] == 'foo'])

產量

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

如果您有多個要選擇的標準,可以將它們放在列表中並使用'isin':

print(df.loc[df['B'].isin(['one','three'])])

產量

      A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

但是請注意,如果您希望多次執行此操作,首先將索引設為A,然後使用df.loc會更有效:

df = df.set_index(['A'])
print(df.loc['foo'])

產量

  A      B  C   D
foo    one  0   0
foo    two  2   4
foo    two  4   8
foo    one  6  12
foo  three  7  14

有幾種基本的方法可以從熊貓數據框中選擇行。

  1. 布爾索引
  2. 位置索引
  3. 標籤索引
  4. API

對於每種基本類型,我們可以通過將自己限制為熊貓API來簡化事情,或者我們可以在API之外進行冒險,通常會變成numpy ,並加快速度。

我會告訴你每個例子,並指導你何時使用某些技術。

建立
我們需要做的第一件事是確定一個條件,作為選擇行的標準。 OP提供了column_name == some_value 。 我們將從那裡開始並包含一些其他常見用例。

借用@unutbu:

import pandas as pd, numpy as np

df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8), 'D': np.arange(8) * 2})

假設我們的標準是'A' = 'foo'

1。
布爾索引需要找到每行'A'列的真值等於'foo' ,然後使用這些真值來確定要保留的行。 通常,我們將這個系列命名為一組真值, mask 。 我們也會在這裡做。

mask = df['A'] == 'foo'

然後我們可以使用這個掩碼來對數據幀進行分片或索引

df[mask]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

這是完成這項任務最簡單的方法之一,如果性能或直覺不成問題,這應該是您選擇的方法。 但是,如果性能是一個問題,那麼您可能需要考慮另一種創建mask

2。
位置索引有其用例,但這不是其中之一。 為了確定切片的位置,我們首先需要執行與上面相同的布爾分析。 這讓我們執行一個額外的步驟來完成相同的任務。

mask = df['A'] == 'foo'
pos = np.flatnonzero(mask)
df.iloc[pos]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

3。
標籤索引可以非常方便,但在這種情況下,我們再次做更多的工作沒有任何好處

df.set_index('A', append=True, drop=False).xs('foo', level=1)

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

4。
pd.DataFrame.query是執行此任務的非常優雅/直觀的方式。 但通常較慢。 但是 ,如果您注意以下時間,對於大數據,查詢非常有效。 比我的最佳建議更像標準方法,並且幅度相當。

df.query('A == "foo"')

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

我的首選是使用Boolean mask

實際的改進可以通過修改我們創建Boolean mask

mask替代1
使用底層numpy數組並放棄創建另一個pd.Series的開銷

mask = df['A'].values == 'foo'

我將在最後展示更完整的時間測試,但只要看看使用示例數據框所獲得的性能提升。 首先我們看一下創建mask的區別

%timeit mask = df['A'].values == 'foo'
%timeit mask = df['A'] == 'foo'

5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

使用numpy陣列評估mask的速度要快30倍。 部分原因是因為評估經常比較快。 這也是由於缺少構建索引和相應的pd.Series對象所需的開銷。

接下來,我們將看看用一個mask與另一個mask切片的時機。

mask = df['A'].values == 'foo'
%timeit df[mask]
mask = df['A'] == 'foo'
%timeit df[mask]

219 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
239 µs ± 7.03 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

性能提升並不明顯。 我們會看看這是否能夠通過更強大的測試。

mask替代2
我們也可以重構數據框。 重建數據dtypes時有一個很大的警告 - 當你這樣做的時候你必須注意dtypes

我們會這樣做,而不是df[mask]

pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)

如果數據框是混合類型,我們的例子是,那麼當我們得到df.values ,得到的數組是df.values object ,因此新數據df.values的所有列將是dtype object 。 因此需要使用astype(df.dtypes)並殺死任何潛在的性能增益。

%timeit df[m]
%timeit pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)

216 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1.43 ms ± 39.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

但是,如果數據框不是混合類型的,這是一個非常有用的方法。

特定

np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))

d1

   A  B  C  D  E
0  0  2  7  3  8
1  7  0  6  8  6
2  0  2  0  4  9
3  7  3  2  4  3
4  3  6  7  7  4
5  5  3  7  5  9
6  8  7  6  4  7
7  6  2  6  6  5
8  2  8  7  5  8
9  4  7  6  1  5    
%%timeit
mask = d1['A'].values == 7
d1[mask]

179 µs ± 8.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%%timeit
mask = d1['A'].values == 7
pd.DataFrame(d1.values[mask], d1.index[mask], d1.columns)

87 µs ± 5.12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

我們把時間縮短了一半。

mask替代3
@unutbu還向我們展示瞭如何使用pd.Series.isin來解釋df['A']中的每個元素是否在一組值中。 如果我們的一組值是一組值,即'foo' ,那麼這個評估就是同樣的事情。 但是如果需要的話,它也推廣到包括更大的值集合。 事實證明,儘管這是一個更為通用的解決方案,但它仍然非常快。 對於那些不熟悉這個概念的人來說,唯一真正的損失是直觀的。

mask = df['A'].isin(['foo'])
df[mask]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

然而,和以前一樣,我們可以利用numpy來提高性能,同時幾乎可以褻瀆任何東西。 我們將使用np.in1d

mask = np.in1d(df['A'].values, ['foo'])
df[mask]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

定時
我將包括其他文章中提到的其他概念以供參考。
代碼如下

此表中的每個列表示一個不同長度的數據幀,我們將在其中測試每個函數。 每列顯示相對所用的時間,給出基礎指數為1.0的最快函數。

res.div(res.min())

                         10        30        100       300       1000      3000      10000     30000
mask_standard         2.156872  1.850663  2.034149  2.166312  2.164541  3.090372  2.981326  3.131151
mask_standard_loc     1.879035  1.782366  1.988823  2.338112  2.361391  3.036131  2.998112  2.990103
mask_with_values      1.010166  1.000000  1.005113  1.026363  1.028698  1.293741  1.007824  1.016919
mask_with_values_loc  1.196843  1.300228  1.000000  1.000000  1.038989  1.219233  1.037020  1.000000
query                 4.997304  4.765554  5.934096  4.500559  2.997924  2.397013  1.680447  1.398190
xs_label              4.124597  4.272363  5.596152  4.295331  4.676591  5.710680  6.032809  8.950255
mask_with_isin        1.674055  1.679935  1.847972  1.724183  1.345111  1.405231  1.253554  1.264760
mask_with_in1d        1.000000  1.083807  1.220493  1.101929  1.000000  1.000000  1.000000  1.144175

您會注意到最快的時間似乎在mask_with_valuesmask_with_in1d之間共享

res.T.plot(loglog=True)

功能

def mask_standard(df):
    mask = df['A'] == 'foo'
    return df[mask]

def mask_standard_loc(df):
    mask = df['A'] == 'foo'
    return df.loc[mask]

def mask_with_values(df):
    mask = df['A'].values == 'foo'
    return df[mask]

def mask_with_values_loc(df):
    mask = df['A'].values == 'foo'
    return df.loc[mask]

def query(df):
    return df.query('A == "foo"')

def xs_label(df):
    return df.set_index('A', append=True, drop=False).xs('foo', level=-1)

def mask_with_isin(df):
    mask = df['A'].isin(['foo'])
    return df[mask]

def mask_with_in1d(df):
    mask = np.in1d(df['A'].values, ['foo'])
    return df[mask]

測試

res = pd.DataFrame(
    index=[
        'mask_standard', 'mask_standard_loc', 'mask_with_values', 'mask_with_values_loc',
        'query', 'xs_label', 'mask_with_isin', 'mask_with_in1d'
    ],
    columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    dtype=float
)

for j in res.columns:
    d = pd.concat([df] * j, ignore_index=True)
    for i in res.index:a
        stmt = '{}(d)'.format(i)
        setp = 'from __main__ import d, {}'.format(i)
        res.at[i, j] = timeit(stmt, setp, number=50)

特殊時間
當我們對整個數據幀有單個非對象dtype時,看一下特殊情況。 代碼如下

spec.div(spec.min())

                     10        30        100       300       1000      3000      10000     30000
mask_with_values  1.009030  1.000000  1.194276  1.000000  1.236892  1.095343  1.000000  1.000000
mask_with_in1d    1.104638  1.094524  1.156930  1.072094  1.000000  1.000000  1.040043  1.027100
reconstruct       1.000000  1.142838  1.000000  1.355440  1.650270  2.222181  2.294913  3.406735

原來,重建不值得它過去幾百行。

spec.T.plot(loglog=True)

功能

np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))

def mask_with_values(df):
    mask = df['A'].values == 'foo'
    return df[mask]

def mask_with_in1d(df):
    mask = np.in1d(df['A'].values, ['foo'])
    return df[mask]

def reconstruct(df):
    v = df.values
    mask = np.in1d(df['A'].values, ['foo'])
    return pd.DataFrame(v[mask], df.index[mask], df.columns)

spec = pd.DataFrame(
    index=['mask_with_values', 'mask_with_in1d', 'reconstruct'],
    columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    dtype=float
)

測試

for j in spec.columns:
    d = pd.concat([df] * j, ignore_index=True)
    for i in spec.index:
        stmt = '{}(d)'.format(i)
        setp = 'from __main__ import d, {}'.format(i)
        spec.at[i, j] = timeit(stmt, setp, number=50)

為了追加到這個著名的問題中(儘管有點太晚了):你也可以通過df.groupby('column_name').get_group('column_desired_value').reset_index()來創建一個新的數據框,其中指定的列有一個特定的值。 例如

import pandas as pd
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split()})
print("Original dataframe:")
print(df)

b_is_two_dataframe = pd.DataFrame(df.groupby('B').get_group('two').reset_index()).drop('index', axis = 1) 
#NOTE: the final drop is to remove the extra index column returned by groupby object
print('Sub dataframe where B is two:')
print(b_is_two_dataframe)

運行這個給出:

Original dataframe:
     A      B
0  foo    one
1  bar    one
2  foo    two
3  bar  three
4  foo    two
5  bar    two
6  foo    one
7  foo  three
Sub dataframe where B is two:
     A    B
0  foo  two
1  foo  two
2  bar  two

這是一個簡單的例子

from pandas import DataFrame

# Create data set
d = {'Revenue':[100,111,222], 
     'Cost':[333,444,555]}
df = DataFrame(d)


# mask = Return True when the value in column "Revenue" is equal to 111
mask = df['Revenue'] == 111

print mask

# Result:
# 0    False
# 1     True
# 2    False
# Name: Revenue, dtype: bool


# Select * FROM df WHERE Revenue = 111
df[mask]

# Result:
#    Cost    Revenue
# 1  444     111

df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8), 'D': np.arange(8) * 2})
df[df['A']=='foo']

OUTPUT:
   A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14






dataframe