Leer archivo de Excel en Python


88

Tengo un archivo de Excel

Arm_id      DSPName        DSPCode          HubCode          PinCode    PPTL
1            JaVAS            01              AGR             282001    1,2
2            JaVAS            01              AGR             282002    3,4
3            JaVAS            01              AGR             282003    5,6

Quiero guardar una cadena en el formulario Arm_id,DSPCode,Pincode. Este formato es configurable, es decir, puede cambiar a DSPCode,Arm_id,Pincode. Lo guardo en una lista como:

FORMAT = ['Arm_id', 'DSPName', 'Pincode']

¿Cómo leo el contenido de una columna específica con el nombre proporcionado, dado que FORMATes configurable?

Esto es lo que intenté. Actualmente puedo leer todo el contenido del archivo.

from xlrd import open_workbook
wb = open_workbook('sample.xls')
for s in wb.sheets():
    #print 'Sheet:',s.name
    values = []
    for row in range(s.nrows):
        col_value = []
        for col in range(s.ncols):
            value  = (s.cell(row,col).value)
            try : value = str(int(value))
            except : pass
            col_value.append(value)
        values.append(col_value)
print values

Mi salida es

[[u'Arm_id', u'DSPName', u'DSPCode', u'HubCode', u'PinCode', u'PPTL'], ['1', u'JaVAS', '1', u'AGR', '282001', u'1,2'], ['2', u'JaVAS', '1', u'AGR', '282002', u'3,4'], ['3', u'JaVAS', '1', u'AGR', '282003', u'5,6']]

Luego hago un bucle values[0]tratando de averiguar el FORMATcontenido values[0]y luego obtengo el índice de Arm_id, DSPname and Pincodeen el values[0]y luego, del siguiente bucle, conozco el índice de todos los FORMATfactores, por lo que sé qué valor necesito obtener.

Pero esta es una mala solución.

¿Cómo obtengo los valores de una columna específica con nombre en el archivo de Excel?


Debería utilizar dict()ao crear su propia clase de datos.
tamasgal

¿Como que? ¿Puede proporcionar un código de muestra?
PythonEnthusiast

Respuestas:


70

Este es un enfoque:

from xlrd import open_workbook

class Arm(object):
    def __init__(self, id, dsp_name, dsp_code, hub_code, pin_code, pptl):
        self.id = id
        self.dsp_name = dsp_name
        self.dsp_code = dsp_code
        self.hub_code = hub_code
        self.pin_code = pin_code
        self.pptl = pptl

    def __str__(self):
        return("Arm object:\n"
               "  Arm_id = {0}\n"
               "  DSPName = {1}\n"
               "  DSPCode = {2}\n"
               "  HubCode = {3}\n"
               "  PinCode = {4} \n"
               "  PPTL = {5}"
               .format(self.id, self.dsp_name, self.dsp_code,
                       self.hub_code, self.pin_code, self.pptl))

wb = open_workbook('sample.xls')
for sheet in wb.sheets():
    number_of_rows = sheet.nrows
    number_of_columns = sheet.ncols

    items = []

    rows = []
    for row in range(1, number_of_rows):
        values = []
        for col in range(number_of_columns):
            value  = (sheet.cell(row,col).value)
            try:
                value = str(int(value))
            except ValueError:
                pass
            finally:
                values.append(value)
        item = Arm(*values)
        items.append(item)

for item in items:
    print item
    print("Accessing one single value (eg. DSPName): {0}".format(item.dsp_name))
    print

No tiene que usar una clase personalizada, simplemente puede tomar un dict(). Sin embargo, si usa una clase, puede acceder a todos los valores a través de la notación de puntos, como puede ver arriba.

Aquí está la salida del script anterior:

Arm object:
  Arm_id = 1
  DSPName = JaVAS
  DSPCode = 1
  HubCode = AGR
  PinCode = 282001 
  PPTL = 1
Accessing one single value (eg. DSPName): JaVAS

Arm object:
  Arm_id = 2
  DSPName = JaVAS
  DSPCode = 1
  HubCode = AGR
  PinCode = 282002 
  PPTL = 3
Accessing one single value (eg. DSPName): JaVAS

Arm object:
  Arm_id = 3
  DSPName = JaVAS
  DSPCode = 1
  HubCode = AGR
  PinCode = 282003 
  PPTL = 5
Accessing one single value (eg. DSPName): JaVAS

90

Una respuesta algo tardía, pero con pandas, es posible obtener directamente una columna de un archivo de Excel:

import pandas

df = pandas.read_excel('sample.xls')
#print the column names
print df.columns
#get the values for a given column
values = df['Arm_id'].values
#get a data frame with selected columns
FORMAT = ['Arm_id', 'DSPName', 'Pincode']
df_selected = df[FORMAT]

Asegúrese de haber instalado xlrd y pandas:

pip install pandas xlrd

2
Agregue import xlrden la parte superior para que esto funcione. read_excelrequiere xlrd. Si lo consigue ImportError: No module named 'xlrd', hágalopip install xlrd
nishant

9
no se requiere importar xlrd, solo asegúrese de que xlrd esté instalado, pandas lo importará y lo usará.
Vaibhav Vishal

12

Entonces, las partes clave son tomar el encabezado ( col_names = s.row(0)) y, al iterar a través de las filas, omitir la primera fila que no es necesaria for row in range(1, s.nrows), lo que se hace usando el rango de 1 en adelante (no el 0 implícito). Luego, usa zip para recorrer las filas que tienen 'nombre' como encabezado de la columna.

from xlrd import open_workbook

wb = open_workbook('Book2.xls')
values = []
for s in wb.sheets():
    #print 'Sheet:',s.name
    for row in range(1, s.nrows):
        col_names = s.row(0)
        col_value = []
        for name, col in zip(col_names, range(s.ncols)):
            value  = (s.cell(row,col).value)
            try : value = str(int(value))
            except : pass
            col_value.append((name.value, value))
        values.append(col_value)
print values


2

Aquí está el código para leer un archivo de Excel e imprimir todas las celdas presentes en la columna 1 (excepto la primera celda, es decir, el encabezado):

import xlrd

file_location="C:\pythonprog\xxx.xlsv"
workbook=xlrd.open_workbook(file_location)
sheet=workbook.sheet_by_index(0)
print(sheet.cell_value(0,0))

for row in range(1,sheet.nrows):
     print(sheet.cell_value(row,0))

1

El enfoque que tomé lee la información del encabezado de la primera fila para determinar los índices de las columnas de interés.

Mencionó en la pregunta que también desea que los valores se envíen a una cadena. Construyo dinámicamente una cadena de formato para la salida de la lista de columnas FORMAT. Las filas se añaden a la cadena de valores separados por un nuevo carácter de línea.

El orden de las columnas de salida está determinado por el orden de los nombres de las columnas en la lista FORMATO.

En mi código a continuación, el caso del nombre de la columna en la lista FORMATO es importante. En la pregunta anterior, tiene 'Pincode' en su lista FORMAT, pero 'PinCode' en su Excel. Esto no funcionaría a continuación, tendría que ser 'PinCode'.

from xlrd import open_workbook
wb = open_workbook('sample.xls')

FORMAT = ['Arm_id', 'DSPName', 'PinCode']
values = ""

for s in wb.sheets():
    headerRow = s.row(0)
    columnIndex = [x for y in FORMAT for x in range(len(headerRow)) if y == firstRow[x].value]
    formatString = ("%s,"*len(columnIndex))[0:-1] + "\n"

    for row in range(1,s.nrows):
        currentRow = s.row(row)
        currentRowValues = [currentRow[x].value for x in columnIndex]
        values += formatString % tuple(currentRowValues)

print values

Para la entrada de muestra que proporcionó anteriormente, este código salidas:

>>> 1.0,JaVAS,282001.0
2.0,JaVAS,282002.0
3.0,JaVAS,282003.0

Y como soy un novato en Python, los apoyos son: esta respuesta , esta respuesta , esta pregunta , esta pregunta y esta respuesta .


Creo que firstRow[x].valuese supone que esheaderRow[x].value
TSeymour

0

Aunque casi siempre uso pandas para esto, mi pequeña herramienta actual está empaquetada en un ejecutable e incluir pandas es excesivo. Así que creé una versión de la solución de poida que resultó en una lista de tuplas con nombre. Su código con este cambio se vería así:

from xlrd import open_workbook
from collections import namedtuple
from pprint import pprint

wb = open_workbook('sample.xls')

FORMAT = ['Arm_id', 'DSPName', 'PinCode']
OneRow = namedtuple('OneRow', ' '.join(FORMAT))
all_rows = []

for s in wb.sheets():
    headerRow = s.row(0)
    columnIndex = [x for y in FORMAT for x in range(len(headerRow)) if y == headerRow[x].value]

    for row in range(1,s.nrows):
        currentRow = s.row(row)
        currentRowValues = [currentRow[x].value for x in columnIndex]
        all_rows.append(OneRow(*currentRowValues))

pprint(all_rows)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.