2014-02-27 92 views
2

Python/pandas n00b。我有處理存儲在csv文件中的事件數據的代碼。來自df["CONTACT PHONE NUMBER"]的數據正在輸出電話號碼爲「5555551212.0」顯然,「.0」是一個問題,但添加因爲它是一個整數,我想?使用pandas在csv中格​​式化電話號碼

Anyhoo,爲了便於使用,我決定格式化電話號碼。

該數字來自未格式化的csv文件。該數字將始終爲十位:5555551212,但我想將其顯示爲(555)555-1212。

import glob 
import os 
import pandas as pd 
import sys 

csvfiles = os.path.join(directory, '*.csv') 
for csvfile in glob.glob(csvfiles): 
    df = pd.read_csv(filename) 
    #formatting the contact phone 
    phone_nos = df["CONTACT PHONE NUMBER"] 
    for phone_no in phone_nos: 
     contactphone = "(%c%c%c)%c%c%c-%c%c%c%c" % tuple(map(ord,phone_no)) 

最後一行給了我以下錯誤: not enough arguments for format string

但也許這是不是這樣做的大熊貓的方式。由於我在遍歷數組,所以我還需要將數據保存在其現有列中,或者在處理完電話號碼後重建該列。

+0

國際海事組織,你應該實際存儲這些字符串(而不是整數)。也許他們正在浮動,因爲你有一些缺失的數據? –

+0

CSV文件是從我們使用的服務生成的,所以我不控制數據的存儲方式。 – mattrweaver

+1

我的意思是,你可以在* DataFrame *中以字符串的形式讀取它,而不是一個int(因爲你有缺失的數據,atm被上浮爲float),請參閱我的回答 –

回答

3

我認爲問題是,手機號碼存儲爲float64,因此,增加了一些事情會解決您的內部循環:

In [75]: 

df['Phone_no'] 
Out[75]: 
0 5554443333 
1 1114445555 
Name: Phone_no, dtype: float64 
In [76]: 

for phone_no in df['Phone_no']: 
    contactphone = "(%c%c%c)%c%c%c-%c%c%c%c" % tuple(map(ord,list(str(phone_no)[:10]))) 
    print contactphone 
(555)444-3333 
(111)444-5555 

不過,我覺得它更容易只是把我的電話號碼爲string(@Andy_Hayden失蹤值取得了良好的點,所以我提出了以下數據集:)

In [121]: 

print df 
    Phone_no Name 
0 5554443333 John 
1 1114445555 Jane 
2   NaN Betty 

[3 rows x 2 columns] 
In [122]: 

df.dtypes 
Out[122]: 
Phone_no float64 
Name   object 
dtype: object 
#In [123]: You don't need to convert the entire DataFrame, only the 'Phone_no' needs to be converted. 
# 
#df=df.astype('S4') 
In [124]: 

df['PhoneNumber']=df['Phone_no'].astype(str).apply(lambda x: '('+x[:3]+')'+x[3:6]+'-'+x[6:10]) 
In [125]: 

print df 
     Phone_no Name PhoneNumber 
0 5554443333.0 John (555)444-3333 
1 1114445555.0 Jane (111)444-5555 
2   NaN Betty   (nan)- 

[3 rows x 3 columns] 

In [134]: 
import numpy as np 
df['PhoneNumber']=df['Phone_no'].astype(str).apply(lambda x: np.where((len(x)>=10)&set(list(x)).issubset(list('.')), 
                     '('+x[:3]+')'+x[3:6]+'-'+x[6:10], 
                     'Phone number not in record')) 
In [135]: 

print df 
    Phone_no Name     PhoneNumber 
0 5554443333 John    (555)444-3333 
1 1114445555 Jane    (111)444-5555 
2   NaN Betty Phone number not in record 

[3 rows x 3 columns] 
+0

(nan) - 對我來說似乎是錯誤的,我想你會希望這是nan或raise和抱怨:s –

+0

謝謝!我得到一個錯誤,'S4沒有定義',但我將行更改爲'df.astype(str)',它工作。 如何保留nan值?這個腳本處理一個csv文件作爲數字標牌的源數據?我寧願將空單元留空。我注意到CSV文件中的另一個空字段現在顯示了它以前沒有做過的「NaN」。 – mattrweaver

+0

嗨馬特,1,'S4'是'numpy'' dtype'字符串。 2,你不需要爲整個'DataFrame'改變'dtype',只有電話號碼列需要'str'。或者做什麼@Andy_Hayden建議,但用's = df ['Phone_no']。astype(str)' –

4

我覺得電話號碼should bestoredas a string
當讀取可以確保該列的CSV讀爲字符串:

pd.read_csv(filename, dtype={"CONTACT PHONE NUMBER": str}) 

您可以使用字符串方法,天真地補充道:

In [11]: s = pd.Series(['5554443333', '1114445555', np.nan, '123']) # df["CONTACT PHONE NUMBER"] 

# phone_nos = '(' + s.str[:3] + ')' + s.str[3:7] + '-' + s.str[7:11] 

編輯:作爲Noah answers在一個相關的問題,你可以更直接/做到這一點使用str.replace有效:

In [12]: phone_nos = s.str.replace('^(\d{3})(\d{3})(\d{4})$', r'(\1)\2-\3') 

In [13]: phone_nos 
Out[13]: 
0 (555)4443-333 
1 (111)4445-555 
2    NaN 
3    123 
dtype: object 

但這裏有一個問題,因爲你有一個發作形成數量,而不是精確的10位數字,所以你可以NaN的那些:

In [14]: s.str.contains('^\d{10}$') # note: NaN is truthy 
Out[14]: 
0  True 
1  True 
2  NaN 
3 False 
dtype: object 

In [15]: phone_nos.where(s.str.contains('^\d{10}$')) 
Out[15]: 
0 (555)4443-333 
1 (111)4445-555 
2    NaN 
3    NaN 
dtype: object 

現在,你可能想考察你(也許你有壞的格式更改輸出到包括它們,例如如果他們包括國家代碼):

In [16]: s[~s.str.contains('^\d{10}$').astype(bool)] 
Out[16]: 
3 123 
dtype: object