rainit2006 / Python-room

my python room
0 stars 0 forks source link

pandas #6

Open rainit2006 opened 7 years ago

rainit2006 commented 7 years ago

Agenda

应用例

rainit2006 commented 7 years ago

まとめ ■サンプルデータではヘッダが 3行目から始まるため、冒頭の 2行を skiprows オプションで読み飛ばす。

fname = 'ny.gdp.mktp.cd_Indicator_en_csv_v2.csv'
df = pd.read_csv(fname, skiprows=[0, 1])

■数据的选择(slice) 1)ix方法已经被废弃了 2).loc,.at,选列是只能是列名,不能是position 3).iloc,.iat,选列是只能是position,不能是列名 4)df[]只能进行行选择,或列选择,不能同时进行列选择,列选择只能是列名。 既然loc只能是名称,iloc只能是数字,那么想选择第300-500行的某个列怎么办? 答案: df[['列1', '列2' ]].iloc[300:500]

■每隔10行取一个数据 df.iloc[::10, :]

■描述Series数据需要先把数据进行格式转换,否则因为数据是str的时候就无法描绘出正确的图形,甚至报错。

data=data.astype(float)
data.plot()

■ 去除'Car.v'里非数据的行

df = df[df['Car.v'].apply(lambda x: type(x) in [int, np.int64, float, np.float64])]
# print(df['Car.v'].head(5))

■删除第2行和第3行 (即使index并不是0-100那样整数有序排列) df.drop(df.index[1:3], inplace=True)

■ 将columns列替换index,用set_index

# 将columns中的其中两列:race和sex的值设置索引,race为一级,sex为二级
# inplace=True 在原数据集上修改的
# inplace 代表是否将column里删除替换index的列
adult.set_index(['race','sex'], inplace = True) 

■取得Series的元素,用get方法

print(data.get(0))
print(type(data.get(0)))

■pandasオブジェクトのメソッドで関数を適用 Seriesの各要素に適用: map(), apply() DataFrameの各要素に適用: applymap() DataFrameの各行・各列に適用: apply()

df = df.applymap(function)

■读取excel

# 在指定sheet里读取指定的列数据
df = pd.read_excel('./data_jupiter/elevation_data.xlsx', sheet_name=r'暫定フィルタ' ,\
 index_col=0, na_values=['NA'], usecols = "A,H")

■绘图plot https://note.nkmk.me/python-pandas-plot/ https://note.nkmk.me/python-seaborn-pandas-pairplot/

df.plot() : 把df里每个列都画出来,自动带有legend。
df.plot(subplots=True, figsize=(9, 5), grid=True)
# 不同列显示在不同图里,figsize可以设定大小,grid代表是否显示网格
df.plot(subplots=True, layout=(2, 2))
# layout表示subplots的layout。上例意思是 2行2列来排放subplot
df.plot(subplots=True, layout=(2, 2),   sharex=True, sharey=True)
# それぞれx軸、y軸の範囲が共通化される。
df.plot(x='sepal_length', y='sepal_width')
# 把df里列'sepal_length'作为x轴,'sepal_width'列作为Y轴
df.plot(x='sepal_length')
# xのみ指定した場合は、残りの列がy軸としてプロットされる。
# yのみ指定した場合は、x軸がindex、指定した列がy軸としてプロットされる。

ax = df.plot(y='sepal_length')
df.plot(y='sepal_width', ax=ax)
# 複数の列を重ねてプロットしたい場合は、1つ目のplot()で取得できるAxesSubplotを2つ目以降のplot()の引数axに指定する。
df[['sepal_length', 'sepal_width']].plot() と一緒。

# グラフの種類: 引数kind
# df.plot(kind='line')とdf.plot.line()は同じ。
df.plot.line(style=['r--', 'b.-', 'g+', 'k:'])
df[:5].plot.bar()
df[:5].plot.barh()

他の引数: 引数title: グラフタイトル 引数grid: グリッドの有無 引数colormap: 色 引数legend: 凡例の有無 引数alpha: 透過率(0〜1)

seabornでペアプロット図(散布図行列)を作成. seaborn.pairplot()関数を使う https://note.nkmk.me/python-seaborn-pandas-pairplot/

结合pyplot来複数のサブプロットを並べる例:

fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(9, 6))
df.plot(ax=axes[0, 0], legend=False)
df.plot(ax=axes[1, 2], legend=False, kind='hist')
fig.savefig('data/dst/pandas_iris_line_axes.png')

image

rainit2006 commented 7 years ago

df=DataFrame({'X':['A', 'B', 'C', 'D', 'E'], 'Y':['AA', 'BB', 'CC', 'DD', 'EE'], 'Z':['AAA', 'BBB', 'CCC', 'DDD', 'EEE']})

print df

----------------

X Y Z

0 A AA AAA

1 B BB BBB

2 C CC CCC

3 D DD DDD

4 E EE EEE

----------------

df.drop([0,2], inplace=True) print df

----------------

X Y Z

1 B BB BBB

3 D DD DDD

4 E EE EEE

----------------

↑ 削除したらインデックスが歯抜けに!

print df.reset_index(drop=True)

----------------

X Y Z

0 B BB BBB

1 D DD DDD

2 E EE EEE

----------------

↑ reset_index で振り直し



drop オプション
drop=True を指定しなければ、旧インデックスがデータ列に移動します。
![image](https://user-images.githubusercontent.com/12871721/29546556-1744969a-8730-11e7-898e-f1d56d4c0cc7.png)

inplace オプション
inplace=True で、オブジェクトを直接書きかえられます。
![image](https://user-images.githubusercontent.com/12871721/29546570-303208e0-8730-11e7-8bf7-68243a4240df.png)
rainit2006 commented 7 years ago

■ df的属性和方法一览: .values : データフレームの要素をnumpyのndarrayの形式で返す。 .dtypes : DataFrameのcolumnsごとのdtypeをまとめたSeriesを返す .loc : ラベルによる選択のための純粋なラベル位置ベースのインデクサー(直訳) .iloc: 位置による選択のための純粋な整数位置ベースの索引付け(直訳) ndim :Return an int representing the number of axes / array dimensions. Return 1 if Series. Otherwise return 2 if DataFrame. .shape:データフレームの行列数を表すタプルを返す。(何行何列か) .size:データフレームの要素数を返す。(行数*列数) .T:行列を入れ替える。(転置行列の取得) axes:Return a list with the row axis labels and column axis labels as the only members. They are returned in that order. select_dtypes : Return a subset of a DataFrame including/excluding columns based on their dtype.

df_data.loc[1] //index的值
df_data.loc[:, "Age"] //Age是一个column值

print(df.iloc[3, 1])
df_data.iloc[:, 0]

df.index  #返回的是index的描述
print(df.index.values) #返回的是值
# ['Alice' 'Bob' 'Charlie' 'Dave' 'Ellen' 'Frank']

df.columns
print(df.columns.values)
# ['age' 'state' 'point']

df_data.axes
#输出
[Int64Index([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
             ...
             408, 409, 410, 411, 412, 413, 414, 415, 416, 417],
            dtype='int64', length=1309),
 Index(['Age', 'Cabin', 'Embarked', 'Fare', 'Name', 'Parch', 'PassengerId',
        'Pclass', 'Sex', 'SibSp', 'Survived', 'Ticket'],
       dtype='object')]

train = df_train.select_dtypes(include=['float64', 'int64'])
df.select_dtypes(exclude=['floating']) #排除某些类型的列

<class 'pandas.core.frame.DataFrame'> RangeIndex: 891 entries, 0 to 890 Data columns (total 6 columns): PassengerId 891 non-null int64 Pclass 891 non-null int64 Age 714 non-null float64 SibSp 891 non-null int64 Parch 891 non-null int64 Fare 891 non-null float64 dtypes: float64(2), int64(4) memory usage: 41.8 KB


- DataFrame.describe
Get a statistical overview
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.describe.html
![image](https://user-images.githubusercontent.com/12871721/43057852-8050a4d8-8e7f-11e8-8913-df260b487108.png)

- Count the missing values in each column, try:

df.isnull().sum()   or df.isnull().sum(axis=0)

- count in each row (which is your question) by:
`df.isnull().sum(axis=1)`

- check if any value is NaN in a Pandas DataFrame
df.isnull().values.any() 等许多方法
详情看:https://stackoverflow.com/questions/29530232/how-to-check-if-any-value-is-nan-in-a-pandas-dataframe

- To find out which rows have NaNs in a specific column:
`nan_rows = df[df['name column'].isnull()]`

- pandas.get_dummies()
文字列でカテゴリー分けされた性別などのデータを、男を0, 女を1のように変換したり、多クラスの特徴量をone-hot表現に変換したりすることができる。機械学習の前処理として行うことが多い。

-------------------------------------------------------------------------
- read data from xls
`df = pd.read_excel('titanic.xls')`

- SV ファイルのロード: 
`df = pd.read_csv("file.csv")`
日语编码的csv文件读取
`df = pd.read_csv('some.csv', encoding='Shift_JIS', na_values='--')`

- 写出文件
df.to_csv('some2.csv')
df.to_csv('some2.csv', index=None) //indexがいらない場合
df.to_csv('some2.csv', index_label='date') //indexに名前をつける場合

- 欠損値の扱い
df = df.dropna()  //欠損値(nan)のある行(index)を削除
df = df.dropna(subset=['temp','depth'])  //特定のcolumn(tempやdepth)に欠損値がある場合,その行を削除する
df = df.fillna(0) //定数(0)で穴埋め
df = df.fillna(method='ffill')  # forward 穴埋め  nan 1.0 nan -> nan 1.0 1.0 (forward  = indexの増加方向 = DataFrameの下方向)
df = df.fillna(method='bfill')  # backward穴埋め  nan 1.0 nan -> 1.0 1.0 nan (backward = indexの減少方向 = DataFrameの上方向)
df = df.interpolate(method='index') //多くの補間手法が用意されている.比如linear, time, index, values, nearest, zero等等。

- df.resample(リサンプル)
時系列データの解像度(頻度)を変更する.
https://qiita.com/okadate/items/7b9620a5e64b4e906c42

- copy dataframe
`original_df = pd.DataFrame.copy(df)`

- drop some specific columns
`df.drop(['body','name'], 1, inplace=True)`
列(columns)を削除するためには、drop()のオプション引数としてaxis=1を指定します。axisは軸を表し、行方向の軸がaxis=0(デフォルト)、列方向の軸がaxis=1となっています。
`df4 = df1.drop('b', axis=1) #delete B column`

- DataFrameを作成し、インデックスを貼り付ける。

Create a DatFrame

df = pd.DataFrame(np.random.randn(6,4),index = dates, columns = list("ABCD")) df

                    A   B   C   D

2013-01-01 0.705624 -0.793903 0.843425 0.672602 2013-01-02 -1.211129 2.077101 -1.795861 0.028060 2013-01-03 0.706086 0.385631 0.967568 0.271894 2013-01-04 2.152279 -0.493576 1.184289 -1.193300 2013-01-05 0.455767 0.787551 0.239406 1.627586 2013-01-06 -0.639162 -0.052620 0.288010 -2.205777

Note: index is not a column.

- sort

df.sort_index(axis=1, ascending=False) //ラベルを降順でソート。 df.sort(columns='B') //ラベル「B」の値で昇順で。


- データを選び出す
`df.loc['20130102':'20130104',['A','B']]  //ラベルとインデックスを両方指定してデータの抜き出し。`

- Group column
`df.groupby('A').sum()`

- データの取得
http://akiyoko.hatenablog.jp/entry/2017/04/03/081630

条件
`df[df['Adj Close'] > 19400]`
`df[df.index < '20160110']`
`df[(df.index.month == 3) & (df.index.day < 10)]`

for i in range(nclusters): temp_df = original_df[ (original_df['cluster_group']==float(i)) ]

rainit2006 commented 7 years ago
rainit2006 commented 6 years ago

统计分析

np.random.seed(1234)
d1 = pd.Series(2*np.random.normal(size = 100)+3)
d2 = np.random.f(2,4,size = 100)
d3 = np.random.randint(1,100,size = 100)
d1.count()  #非空元素计算
d1.min()    #最小值
d1.max()    #最大值
d1.idxmin() #最小值的位置,类似于R中的which.min函数
d1.idxmax() #最大值的位置,类似于R中的which.max函数
d1.quantile(0.1)    #10%分位数
d1.sum()    #求和
d1.mean()   #均值
d1.median() #中位数
d1.mode()   #众数
d1.var()    #方差
d1.std()    #标准差
d1.mad()    #平均绝对偏差
d1.skew()   #偏度
d1.kurt()   #峰度
d1.describe()   #一次性输出多个描述性统计指标

自定义一个函数,将这些统计描述指标全部汇总到一起:

def stats(x):
    return pd.Series([x.count(),x.min(),x.idxmin(),
               x.quantile(.25),x.median(),
               x.quantile(.75),x.mean(),
               x.max(),x.idxmax(),
               x.mad(),x.var(),
               x.std(),x.skew(),x.kurt()],
              index = ['Count','Min','Whicn_Min',
                       'Q1','Median','Q3','Mean',
                       'Max','Which_Max','Mad',
                       'Var','Std','Skew','Kurt'])
stats(d1)

在实际的工作中,我们可能需要处理的是一系列的数值型数据框,如何将这个函数应用到数据框中的每一列呢?可以使用apply函数

df = pd.DataFrame(np.array([d1,d2,d3]).T,columns=['x1','x2','x3'])  ##np.array.T表示将矩阵倒转
df.head()
df.apply(stats)

还可以进行连续变量的相关系数(corr)和协方差矩阵(cov)的求解 df.corr() 关于相关系数的计算可以调用pearson方法或kendell方法或spearman方法,默认使用pearson方法。 df.corr('spearman') 如果只想关注某一个变量与其余变量的相关系数的话,可以使用corrwith,如下方只关心x1与其余变量的相关系数: df.corrwith(df['x1']) 数值型变量间的协方差矩阵 df.cov()

rainit2006 commented 6 years ago

DataFrame DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。 跟其他类似的数据结构相比(如R的data.frame),DataFrame中面向行和面向列的操作基本上是平衡的。

警告: 通过索引方式返回的列只是相应数据的视图而已,并不是副本。因此,对返回的Series所做的任何就地修改全都会反映到源DataFrame上。通过Series的copy方法即可显式地复制列。

重新索引 https://blog.csdn.net/youngbit007/article/details/53067707 pandas对象的一个重要方法是reindex,其作用是创建一个适应新索引的新对象。

obj = Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
obj
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value = 2)
obj2

reindex的插值方法:ffill或pad: 前向填充; bfill或backfill是后向填充。 obj3.reindex(range(6), method='ffill')

对于DataFrame, reindex 可以改变(行)索引,列或两者。当只传入一个序列时,结果中的行被重新索引:

frame = pd.DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'],columns=['Ohio', 'Texas', 'California'])
frame

    Ohio Texas  California
a   0   1   2
c   3   4   5
d   6   7   8

frame2 = frame.reindex(['a', 'b', 'c', 'd'])
frame2
    Ohio    Texas   California
a   0.0 1.0 2.0
b   NaN NaN NaN
c   3.0 4.0 5.0
d   6.0 7.0 8.0

使用column可以将列进行重新索引. 也可以同时读列和index进行reindex,可是插值只在行侧.

pandas最重要的一个功能是,它可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。对于DataFrame,对齐操作会同时发生在行和列上。 image

一个常见的操作是,将函数应用到由各列或行所形成的一维数组上。DataFrame的apply方法即可实现此功能。 许多最为常见的数组统计功能都被实现成DataFrame的方法(如sum和mean),因此无需使用apply方法。 image

排序: 对于Series, obj.sort_index() 对于DataFrame,则可以根据任意一个轴上的索引进行排序:frame.sort_index(axis=1) 降序 frame.sort_index(axis=1, ascending=False) 若要按值对Series进行排序,可使用其order方法: obj.order() 在DataFrame上,你可能希望根据一个或多个列中的值进行排序。将一个或多个列的名字传递给by选项即可达到该目的: frame.sort_index(by='b') 要根据多个列进行排序,传入名称的列表即可:frame.sort_index(by=['a', 'b'])

排名(ranking)跟排序关系密切,且它会增设一个排名值(从1开始,一直到数组中有效数据的数量)

rainit2006 commented 6 years ago

详解 Pandas 透视表(pivot_table) http://python.jobbole.com/81212/

首先,将我们销售渠道的数据读入到数据帧中。

df = pd.read_excel("../in/sales-funnel.xlsx")
df.head()

为方便起见,我们将上表中“Status”列定义为category,并按我们想要的查看方式设置顺序。

df["Status"] = df["Status"].astype("category")
df["Status"].cat.set_categories(["won","pending","presented","declined"], inplace=True)

最简单的透视表必须有一个数据帧和一个索引。 pd.pivot_table(df,index=["Name"]) 或者有多个索引 pd.pivot_table(df,index=["Name","Rep","Manager"]) 通过利用“values”域显式地定义我们关心的列,就可以实现移除那些不关心的列。 pd.pivot_table(df,index=["Manager","Rep"],values=["Price"]) 可以对该列元素进行计数或求和 pd.pivot_table(df,index=["Manager","Rep"],values=["Price"],aggfunc=np.sum) 也可以使用numpy中的函数mean和len来进行计数。 pd.pivot_table(df,index=["Manager","Rep"],values=["Price"],aggfunc=[np.mean,len]) 可以使用“fill_value”将非数值(NaN)设置为0。

pd.pivot_table(df,index=["Manager","Rep"],values=["Price"],
               columns=["Product"],aggfunc=[np.sum],fill_value=0)

margins=True 可以查看数据总和

pd.pivot_table(df,index=["Manager","Rep","Product"],
               values=["Price","Quantity"],
               aggfunc=[np.sum,np.mean],fill_value=0,margins=True)

注意下图里最后一行 “ALL” 就是数据的总和。 image

可以对pivot_table进行查询

table = pd.pivot_table(df,index=["Manager","Status"],columns=["Product"],values=["Quantity","Price"],
               aggfunc={"Quantity":len,"Price":[np.sum,np.mean]},fill_value=0)
table
table.query('Manager == ["Debra Henley"]') //只想查看一个管理者(例如Debra Henley)的数据
table.query('Status == ["pending","won"]') //查看所有的暂停(pending)和成功(won)的交易

总结图: image

rainit2006 commented 6 years ago

•axis=0 もしくは axis='index' で列に対する演算 •axis=1 もしくは axis='columns'で行に対する演算 (デフォルト)

rainit2006 commented 6 years ago

データ連結 / 結合処理 http://sinhrks.hatenablog.com/entry/2015/01/28/073327

横方向に連結したい場合は axis=1 を指定 pd.concat([df1, df4], axis=1) image

引数の各データに共通のラベルのみを残して連結したい場合は join='inner' を指定する。下の例では横連結を指定しているため、共通の index である [2, 3] に対応する行のみが残る。 pd.concat([df1, df4], axis=1, join='inner') image

pd.concat([df1, df4], axis=1, join_axes=[df1.index]) image image

image

ignore_index=True を指定して 連結方向のラベルを 0 から振りなおすことができる。 image

rainit2006 commented 6 years ago

■DataFrameの行、列を削除

DataFrameの行を指定して削除 引数labelsとaxisで指定する。行の場合はaxis=0。デフォルトがaxis=0なので、省略することも可能。 df_new = df.drop(2, axis=0) version 0.21.0以降からは引数indexで指定することもできる。 df_new = df.drop(index=2)

複数の行をまとめて削除する場合はリストで指定する。

df_new = df.drop([0, 2, 4])
df_new = df.drop(index=[0, 2, 4])

デフォルトでは元のDataFrameは変更されず、新しいDataFrameが返される。 引数inplaceをTrueにすると、元のDataFrameが変更される。 この場合、新しいDataFrameは返されず、返り値はNone。

df_org = df.copy()
df_org.drop(index=[0, 2, 4], inplace=True)
print(df_org)

DataFrameの列を指定して削除:引数labelsとaxisで指定する。列の場合はaxis=1。

df_new = df.drop('state', axis=1)
df_new = df.drop(columns='state')
df_new = df.drop(['state', 'point'], axis=1)

複数行・複数列をまとめて削除

df_new = df.drop(index=[0, 2, 4], columns=['state', 'point'])
df_org.drop(index=[0, 2, 4], columns=['state', 'point'], inplace=True)

他の方法 del foo['bar'] # 列を削除する。(pythonのdelを利用している。)

rainit2006 commented 6 years ago

常用处理:

输出:df_data1的第0和第3行数据被提出。

利用这个特性可以实现许多方便的功能,比如:

df_data.loc[(df_data['Fare'].isnull()) , 'Fare'] = fare_to_impute 找到df_data['Fare']列里数据为na的所有行的index,然后给这些行的Fare列数据进行赋值。

rainit2006 commented 6 years ago

常见Error

rainit2006 commented 6 years ago

Pandas中resample方法 https://blog.csdn.net/wangshuang1631/article/details/52314944 Pandas中的resample,重新采样,是对原样本重新处理的一个方法,是一个对常规时间序列数据重新采样和频率转换的便捷的方法。

比如:

  1. 首先创建一个Series,采样频率为一分钟。

    index = pd.date_range('1/1/2000', periods=9, freq='T') series = pd.Series(range(9), index=index)

  2. 降低采样频率为三分钟

    series.resample('3T').sum()

rainit2006 commented 6 years ago

索引设置的变更 https://blog.csdn.net/zhili8866/article/details/68134481

■reindex() 更新index或者columns, 默认:更新index,返回一个新的DataFrame。

# 返回一个新的DataFrame,更新index,原来的index会被替代消失
# 如果dataframe中某个索引值不存在,会自动补上NaN
df2 = df1.reindex(['a','b','c','d','e'])

# fill_valuse为原先不存在的索引补上默认值,不在是NaN
df2 = df1.reindex(['a','b','c','d','e'],  fill_value=0)

# inplace=Ture,在DataFrame上修改数据,而不是返回一个新的DataFrame
df1.reindex(['a','b','c','d','e'],  inplace=Ture)

# reindex不仅可以修改 索引(行),也可以修改列
states = ["Texas","Utah","California"]
df2 = df1.reindex( columns=states )

■set_index() 将DataFrame中的列columns设置成索引index

# 将columns中的其中两列:race和sex的值设置索引,race为一级,sex为二级
# inplace=True 在原数据集上修改的
adult.set_index(['race','sex'], inplace = True) 

# 默认情况下,设置成索引的列会从DataFrame中移除
# drop=False将其保留下来
adult.set_index(['race','sex'], inplace = True) 
rainit2006 commented 6 years ago

两个主要数据结构:Series和DataFrame

Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。 Series的字符串表现形式为:索引在左边,值在右边。由于我们没有为数据指定索引,于是会自动创建一个0到N1(N为数据的长度)的整数型索引。 image image

可以将Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射。它可以用在许多原本需要字典参数的函数中: image

对于许多应用而言,Series最重要的一个功能是:它在算术运算中会自动对齐不同索引的数据。

In [29]: obj3        In [30]: obj4
Out[29]:             Out[30]:
Ohio      35000      California      NaN
Oregon    16000      Ohio          35000
Texas     71000      Oregon        16000
Utah       5000      Texas         71000

In [31]: obj3 + obj4
Out[31]:
California       NaN
Ohio           70000
Oregon         32000
Texas         142000
Utah             NaN

Series对象本身及其索引都有一个name属性.

In [32]: obj4.name = 'population'
In [33]: obj4.index.name = 'state'
rainit2006 commented 6 years ago

■pandasオブジェクトのメソッドで関数を適用 Seriesの各要素に適用: map(), apply() DataFrameの各要素に適用: applymap() DataFrameの各行・各列に適用: apply()

Summing up, apply works on a row / column basis of a DataFrame, applymap works element-wise on a DataFrame, and map works element-wise on a Series.

df = df.applymap(function)

s = df['a']
print(s)
# 0    11
# 1    21
# 2    31
# Name: a, dtype: int64

f_brackets = lambda x: '[{}]'.format(x)
print(s.map(f_brackets))
# 0    [11]
# 1    [21]
# 2    [31]
# Name: a, dtype: object

def f_str(x):
    return str(x).replace('1', 'One').replace('2', 'Two').replace('3', 'Three').replace('4', 'Four')

print(s.map(f_str))
# 0      OneOne
# 1      TwoOne
# 2    ThreeOne
# Name: a, dtype: object