แปลงลอยเป็น ints ใน Pandas หรือไม่


230

ฉันทำงานกับข้อมูลที่นำเข้าจาก CSV นุ่นเปลี่ยนบางคอลัมน์ให้ลอยดังนั้นตอนนี้ตัวเลขในคอลัมน์เหล่านี้จะแสดงเป็นจุดลอยตัว! อย่างไรก็ตามฉันต้องการให้แสดงเป็นจำนวนเต็มหรือไม่มีเครื่องหมายจุลภาค มีวิธีการแปลงเป็นจำนวนเต็มหรือไม่แสดงเครื่องหมายจุลภาคหรือไม่


22
คุณสามารถเปลี่ยนประเภท (ตราบใดที่ไม่มีค่าที่ขาดหายไป)df.col = df.col.astype(int)
EdChum

คำถามนี้เป็นคำถามสองข้อในเวลาเดียวกันและชื่อของคำถามนี้สะท้อนเพียงหนึ่งคำถามเท่านั้น
Monica Heddneck

สำหรับคนที่กดปุ่มด้านบนและพบว่ามีประโยชน์ในแนวคิด แต่ไม่ได้ผลสำหรับคุณนี่เป็นรุ่นที่ทำงานให้ฉันใน python 3.7.5 กับ pandas X:df = df.astype(int)
Oliver.R

คำตอบ:


217

หากต้องการแก้ไขเอาต์พุตลอยทำสิ่งนี้:

df= pd.DataFrame(range(5), columns=['a'])
df.a = df.a.astype(float)
df

Out[33]:

          a
0 0.0000000
1 1.0000000
2 2.0000000
3 3.0000000
4 4.0000000

pd.options.display.float_format = '{:,.0f}'.format
df

Out[35]:

   a
0  0
1  1
2  2
3  3
4  4

16
ขอบคุณ! ฉันปรับสิ่งนี้ใน to_csv: fin.to_csv ('my_table.csv', float_format = '%. f') มันได้ผล!
MJP

4
ในเวอร์ชันล่าสุดของ pandas คุณต้องเพิ่ม copy = False ไปยังอาร์กิวเมนต์ของ astype เพื่อหลีกเลี่ยงคำเตือน
g.stevo

จำเป็นdf.a = df.a.astype(float)หรือไม่ สิ่งนี้ทำสำเนาหรือไม่ (ไม่แน่ใจว่าcopyจะastype()ใช้พารามิเตอร์อย่างไร)? ยังมีการปรับปรุงประเภท "ในสถานที่" หรือไม่?
Mr_and_Mrs_D

1
@EdChum มีวิธีป้องกันไม่ให้ Pandas แปลงประเภทเริ่มต้นด้วยหรือไม่ ตัวอย่างเช่นลองDF.({'200': {'#': 354, '%': 0.9971830985915493}, '302': {'#': 1, '%': 0.0028169014084507044}}) หมายเหตุ # รับการแปลงเป็นแบบลอยและเป็นแถวไม่ใช่คอลัมน์ เพราะแต่ละSeriesอันเป็นแบบเดียวที่สามารถเก็บชุดเครื่องแบบได้หรือไม่
alancalvitti

@alancalvitti สิ่งที่เป็นความตั้งใจของคุณที่นี่เพื่อรักษาค่าหรือdtype? ถ้าเป็นเช่นdtypeนั้นคุณจำเป็นต้องสร้างคอลัมน์เหล่านั้นdtype objectเพื่อให้สามารถผสมกันได้มิฉะนั้นคำแนะนำของฉันคือใช้ลอยและเมื่อทำการเปรียบเทียบใช้np.isclose
EdChum

180

ใช้pandas.DataFrame.astype(<type>)ฟังก์ชั่นเพื่อจัดการคอลัมน์ประเภท

>>> df = pd.DataFrame(np.random.rand(3,4), columns=list("ABCD"))
>>> df
          A         B         C         D
0  0.542447  0.949988  0.669239  0.879887
1  0.068542  0.757775  0.891903  0.384542
2  0.021274  0.587504  0.180426  0.574300
>>> df[list("ABCD")] = df[list("ABCD")].astype(int)
>>> df
   A  B  C  D
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0

แก้ไข:

ในการจัดการค่าที่หายไป:

>>> df
          A         B     C         D
0  0.475103  0.355453  0.66  0.869336
1  0.260395  0.200287   NaN  0.617024
2  0.517692  0.735613  0.18  0.657106
>>> df[list("ABCD")] = df[list("ABCD")].fillna(0.0).astype(int)
>>> df
   A  B  C  D
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0

3
ฉันลองวิธีการของคุณแล้วมันทำให้ฉันมี ValueError: ไม่สามารถแปลง NA เป็นจำนวนเต็ม
MJP

6
@MJP คุณไม่สามารถแปลงอนุกรมจาก float เป็นจำนวนเต็มหากมีค่าหายไปโปรดดูที่pandas.pydata.org/pandas-docs/stable/ ......คุณต้องใช้ float
EdChum

2
ค่าจะไม่หายไป แต่คอลัมน์ไม่ได้ระบุค่าสำหรับแต่ละแถวตามวัตถุประสงค์ มีวิธีใดบ้างที่จะประสบความสำเร็จในการแก้ปัญหา? เนื่องจากค่าเหล่านั้นเป็นรหัสต่างประเทศฉันจึงต้องการค่า int
MJP

4
ฉันได้ทำการแก้ไขซึ่ง NaN ทั้งหมดจะถูกแทนที่ด้วย 0.0
Ryan G

3
หรือดีกว่าถ้าคุณเพียงแก้ไข CSV ดังนั้น: df.to_csv ("path.csv", na_rep = "", float_format = "%. 0f", index = False) แต่สิ่งนี้จะแก้ไขการลอยทั้งหมดดังนั้น อาจเป็นการดีกว่าที่จะแปลงคอลัมน์ FK ของคุณเป็นสตริงทำการจัดการและบันทึก
Ryan G

44

พิจารณากรอบข้อมูลต่อไปนี้:

>>> df = pd.DataFrame(10*np.random.rand(3, 4), columns=list("ABCD"))
>>> print(df)
...           A         B         C         D
... 0  8.362940  0.354027  1.916283  6.226750
... 1  1.988232  9.003545  9.277504  8.522808
... 2  1.141432  4.935593  2.700118  7.739108

ใช้รายการชื่อคอลัมน์เปลี่ยนประเภทสำหรับหลายคอลัมน์ด้วยapplymap():

>>> cols = ['A', 'B']
>>> df[cols] = df[cols].applymap(np.int64)
>>> print(df)
...    A  B         C         D
... 0  8  0  1.916283  6.226750
... 1  1  9  9.277504  8.522808
... 2  1  4  2.700118  7.739108

หรือสำหรับคอลัมน์เดียวกับapply():

>>> df['C'] = df['C'].apply(np.int64)
>>> print(df)
...    A  B  C         D
... 0  8  0  1  6.226750
... 1  1  9  9  8.522808
... 2  1  4  2  7.739108

5
เกิดอะไรขึ้นถ้ามี NaN ในค่าหรือไม่
Zhang18

3
@ Zhang18 ฉันลองใช้วิธีนี้และในกรณีของ NaN คุณมีข้อผิดพลาดนี้:ValueError: ('cannot convert float NaN to integer', u'occurred at index <column_name>')
enri

2
@enri: สามารถลองใช้รหัสต่อไปนี้ -df['C'] = df['C'].dropna().apply(np.int64)
vsdaking

12

นี่เป็นวิธีแก้ปัญหาอย่างรวดเร็วในกรณีที่คุณต้องการแปลงคอลัมน์เพิ่มเติมของคุณpandas.DataFrameจากการลอยเป็นจำนวนเต็มพิจารณากรณีที่คุณสามารถมีค่า NaN

cols = ['col_1', 'col_2', 'col_3', 'col_4']
for col in cols:
   df[col] = df[col].apply(lambda x: int(x) if x == x else "")

ฉันพยายามด้วยelse x)และแต่ผลที่ได้ยังคงมีจำนวนลอยดังนั้นผมจึงใช้else None)else ""


มันจะใช้""กับค่าทั้งหมดในcol
Raheel

มันจะใช้สตริงที่ว่างเปล่า ("") กับค่าที่หายไปทั้งหมดหากนั่นคือสิ่งที่จำเป็น แต่ค่าที่เหลือจะเป็นจำนวนเต็ม
Krzysztof Słowiński

ขอบคุณสำหรับสิ่งนี้. สิ่งนี้ใช้ได้เมื่อ .astype () และ .apply (np.int64) ไม่ทำงาน
Alison S

นี่รู้สึกแฮ็คและฉันไม่เห็นเหตุผลที่จะใช้มันกับตัวเลือกอื่น ๆ
AMC

8

การขยายบน @Ryan G ที่กล่าวถึงการใช้งานของpandas.DataFrame.astype(<type>)วิธีการหนึ่งสามารถใช้errors=ignoreอาร์กิวเมนต์เพื่อแปลงคอลัมน์เหล่านั้นเท่านั้นที่ไม่สร้างข้อผิดพลาดซึ่งทำให้ไวยากรณ์ง่ายขึ้น เห็นได้ชัดว่าควรใช้ความระมัดระวังเมื่อละเว้นข้อผิดพลาด แต่สำหรับงานนี้มันมีประโยชน์มาก

>>> df = pd.DataFrame(np.random.rand(3, 4), columns=list('ABCD'))
>>> df *= 10
>>> print(df)
...           A       B       C       D
... 0   2.16861 8.34139 1.83434 6.91706
... 1   5.85938 9.71712 5.53371 4.26542
... 2   0.50112 4.06725 1.99795 4.75698

>>> df['E'] = list('XYZ')
>>> df.astype(int, errors='ignore')
>>> print(df)
...     A   B   C   D   E
... 0   2   8   1   6   X
... 1   5   9   5   4   Y
... 2   0   4   1   4   Z

จากpandas.DataFrame.astypeเอกสาร:

ข้อผิดพลาด: {'เพิ่ม', 'ละเว้น'}, เริ่มต้น 'เพิ่ม'

ควบคุมการเพิ่มข้อยกเว้นเกี่ยวกับข้อมูลที่ไม่ถูกต้องสำหรับประเภท dtype ที่ให้ไว้

  • เพิ่ม: อนุญาตข้อยกเว้นที่จะยกระดับ
  • ละเว้น: ระงับข้อยกเว้น ในข้อผิดพลาดส่งคืนวัตถุต้นฉบับ

ใหม่ในเวอร์ชั่น 0.20.0


7
>>> import pandas as pd
>>> right = pd.DataFrame({'C': [1.002, 2.003], 'D': [1.009, 4.55], 'key': ['K0', 'K1']})
>>> print(right)
           C      D key
    0  1.002  1.009  K0
    1  2.003  4.550  K1
>>> right['C'] = right.C.astype(int)
>>> print(right)
       C      D key
    0  1  1.009  K0
    1  2  4.550  K1

5

หากต้องการแปลงคอลัมน์ลอยทั้งหมดให้เป็น int

>>> df = pd.DataFrame(np.random.rand(5, 4) * 10, columns=list('PQRS'))
>>> print(df)
...     P           Q           R           S
... 0   4.395994    0.844292    8.543430    1.933934
... 1   0.311974    9.519054    6.171577    3.859993
... 2   2.056797    0.836150    5.270513    3.224497
... 3   3.919300    8.562298    6.852941    1.415992
... 4   9.958550    9.013425    8.703142    3.588733

>>> float_col = df.select_dtypes(include=['float64']) # This will select float columns only
>>> # list(float_col.columns.values)
>>> for col in float_col.columns.values:
...     df[col] = df[col].astype('int64')
>>> print(df)
...     P   Q   R   S
... 0   4   0   8   1
... 1   0   9   6   3
... 2   2   0   5   3
... 3   3   8   6   1
... 4   9   9   8   3

0

นี่คือฟังก์ชั่นพื้นฐานที่จะลดความเร็วลงเป็นจำนวนเต็มน้อยที่สุดเท่าที่จะเป็นไปได้ซึ่งจะไม่ทำให้ข้อมูลสูญหาย ตัวอย่าง,

  • 100.0 สามารถแปลงจากการลอยเป็นจำนวนเต็ม แต่ 99.9 ไม่สามารถ (โดยไม่สูญเสียข้อมูลการปัดเศษหรือการตัด)

  • นอกจากนี้ 1.0 สามารถ downcast ไปตลอดทางint8โดยไม่สูญเสียข้อมูล แต่ประเภทจำนวนเต็มน้อยที่สุดสำหรับ 100_000.0 คือint32

ตัวอย่างรหัส:

import numpy as np
import pandas as pd

def float_to_int( s ):
    if ( s.astype(np.int64) == s ).all():
        return pd.to_numeric( s, downcast='integer' )
    else:
        return s

# small integers are downcast into 8-bit integers
float_to_int( np.array([1.0,2.0]) )
Out[1]:array([1, 2], dtype=int8)

# larger integers are downcast into larger integer types
float_to_int( np.array([100_000.,200_000.]) )
Out[2]: array([100000, 200000], dtype=int32)

# if there are values to the right of the decimal
# point, no conversion is made
float_to_int( np.array([1.1,2.2]) )
Out[3]: array([ 1.1,  2.2])

0

คอลัมน์ที่ต้องถูกแปลงเป็น int สามารถพูดถึงในพจนานุกรมได้เช่นกัน

df = df.astype({'col1': 'int', 'col2': 'int', 'col3': 'int'})

-5
>>> df_18['cyl'].value_counts()
... 4.0     365
... 6.0     246
... 8.0     153

>>> df_18['cyl'] = df_18['cyl'].astype(int)
>>> df_18['cyl'].value_counts()
... 4     365
... 6     246
... 8     153

1
astype(int)ถูกกล่าวถึงหลายครั้งแล้ว คำตอบนี้ไม่ได้เพิ่มอะไรใหม่
Georgy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.