Python pandas возвращает значение из другого столбца - PullRequest
0 голосов
/ 10 октября 2018

У меня есть файл "kindlist.txt", который содержит следующую информацию:

Bacillus,genus
Borrelia,genus
Burkholderia,genus
Campylobacter,genus

Теперь я хочу, чтобы python искал переменную в первом столбце (в этом примере "Campylobacter") ивернуть значение второго («род»).Я написал следующий код

import csv
import pandas as pd

species_import = 'Campylobacter'
df = pd.read_csv('specieslist.txt', header=None, names = ['species', 'level'] )
input = df.loc[df['species'] == species_import]
print (input['level'])

Однако мой код возвращает слишком много, а мне нужен только "род"

3    genus
Name: level, dtype: object

Ответы [ 4 ]

0 голосов
/ 10 октября 2018

Производительность различных методов, чтобы продемонстрировать, когда полезно использовать next(...).

n = 10**6
df = pd.DataFrame({'species': ['b']+['a']*n, 'level': np.arange(n+1)})

def get_first_val(val):
    try:
        return df.loc[df['species'] == val, 'level'].iat[0]
    except IndexError:
        return 'no match'

%timeit next(iter(df.loc[df['species'] == 'b', 'level']), 'no match')     # 123 ms per loop
%timeit get_first_val('b')                                                # 125 ms per loop
%timeit next(idx for idx, val in enumerate(df['species']) if val == 'b')  # 20.3 µs per loop
0 голосов
/ 10 октября 2018

get

С помощью pandas.Series.get вы можете вернуть либо скалярное значение, если 'species' уникально, либо pandas.Series, если не уникально.

f = df.set_index('species').level.get

f('Campylobacter')

'genus'

Есликроме данных, вы можете указать значение по умолчанию

f('X', 'Not In Data')

'Not In Data'

Мы также можем использовать dict.get и возвращать только скаляры.Если не уникально, возвращается последний.

f = dict(zip(df.species, df.level)).get

Если вы хотите вернуть первый, вы можете сделать это несколькими способами

f = dict(zip(df.species[::-1], df.level[::-1])).get 

Или

f = df.drop_duplicates('species').pipe(
    lambda d: dict(zip(d.species, d.level)).get
)
0 голосов
/ 10 октября 2018
# Change the last line of your code to 
print(input['level'].values) 
# For Explanation refer below code

import csv
import pandas as pd

species_import = 'Campylobacter'
df = pd.read_csv('specieslist.txt', header=None, names = ['species', 'level'] )

input = df['species'] == species_import # return a pandas dataFrame

print(type(df[input])) # return a Pandas DataFrame

print(type(df[input]['level'])) # return a Pandas Series 

# To obtain the value from this Series.
print(df[input]['level'].values)  # return 'genus'
0 голосов
/ 10 октября 2018

Вы можете выбрать первое значение Серии с помощью iat:

species_import = 'Campylobacter'
out = df.loc[df['species'] == species_import, 'level'].iat[0]
#alternative
#out = df.loc[df['species'] == species_import, 'level'].values[0]
print (out)
genus

Лучшее решение работает, если не найдено ни одного значения и возвращается empty Series - возвращается no match:

@ jpp comment
Это решение лучше, только если у вас большая серия, и ожидаемое значение будет около верха

species_import = 'Campylobacter'
out = next(iter(df.loc[df['species'] == species_import, 'level']), 'no match')
print (out)
genus

РЕДАКТИРОВАТЬ:

Идея из комментариев, спасибо @jpp:

def get_first_val(val):
    try:
        return df.loc[df['species'] == val, 'level'].iat[0]
    except IndexError:
        return 'no match'

print (get_first_val(species_import))
genus

print (get_first_val('aaa'))
no match

РЕДАКТИРОВАТЬ:

df = pd.DataFrame({'species':['a'] * 10000 + ['b'], 'level':np.arange(10001)})

def get_first_val(val):
    try:
        return df.loc[df['species'] == val, 'level'].iat[0]
    except IndexError:
        return 'no match'


In [232]: %timeit next(iter(df.loc[df['species'] == 'a', 'level']), 'no match')
1.3 ms ± 33.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [233]: %timeit (get_first_val('a'))
1.1 ms ± 21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)



In [235]: %timeit (get_first_val('b'))
1.48 ms ± 206 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [236]: %timeit next(iter(df.loc[df['species'] == 'b', 'level']), 'no match')
1.24 ms ± 10.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...