簡體   English   中英

python用條件重新編碼csv

[英]python recode csv with condition

我是python的初學者。 我需要重新編碼一個 CSV 文件:

unique_id,pid,Age
1,1,1
1,2,3
2,1,5
2,2,6
3,1,6
3,2,4
3,3,6
3,4,1
3,5,4
4,1,6
4,2,5

條件是:對於每個[unique_id],如果有任何[Age]==6,則在[pid]=1的對應行中放一個值1,其他的應該是0。

輸出 csv 將如下所示:

unique_id,pid,Age,recode
1,1,1,0
1,2,3,0
2,1,5,1
2,2,6,0
3,1,6,1
3,2,4,0
3,3,6,0
3,4,1,0
3,5,4,0
4,1,6,1
4,2,5,0

我正在使用 numpy: 就像以下內容:

import numpy
input_file1 = "data.csv"
input_folder = 'G:/My Drive/'
Her_HH =pd.read_csv(input_folder + input_file1)
Her_HH['recode'] = numpy.select([Her_PP['Age']==6,Her_PP['Age']<6], [1,0], default=Her_HH['recode'])

Her_HH.to_csv('recode_elderly.csv', index=False)

但它不會將值 1 放在 [pid] 為 1 的位置。任何幫助將不勝感激。

您可以將DataFrame.assign用於帶有GroupBy.transform新列,如果GroupBy.transform至少有一個匹配GroupBy.any ,則可以使用DataFrame.assign進行測試,測試1鏈掩碼與&用於按位與,最后將輸出轉換為整數

#sorting if necessary
df = df.sort_values('unique_id')

m1 = df.assign(test=df['Age'] == 6).groupby('unique_id')['test'].transform('any')

獲取6組的另一個想法是使用unique_idSeries.isin過濾它們:

m1 = df['unique_id'].isin(df.loc[df['Age'] == 6, 'unique_id'])

m2 = df['pid'] == 1

df['recode'] = (m1 & m2).astype(int)
print (df)
    unique_id  pid  Age  recode
0           1    1    1       0
1           1    2    3       0
2           2    1    5       1
3           2    2    6       0
4           3    1    6       1
5           3    2    4       0
6           3    3    6       0
7           3    4    1       0
8           3    5    4       0
9           4    1    6       1
10          4    2    5       0

編輯:

對於 Age 列中沒有匹配 6 的檢查組,可以通過~倒置掩碼過濾,如果只需要根據unique_id值添加所有唯一行, unique_id添加DataFrame.drop_duplicates

print (df[~m1])
   unique_id  pid  Age
0          1    1    1
1          1    2    3

df1 = df[~m1].drop_duplicates('unique_id')
print (df1)
   unique_id  pid  Age
0          1    1    1

這有點笨拙,因為我比pandas更了解numpy

將您的 csv 樣本加載到數據框中:

In [205]: df = pd.read_csv('stack59885878.csv')                                                  
In [206]: df                                                                                     
Out[206]: 
    unique_id  pid  Age
0           1    1    1
1           1    2    3
2           2    1    5
3           2    2    6
4           3    1    6
5           3    2    4
6           3    3    6
7           3    4    1
8           3    5    4
9           4    1    6
10          4    2    5

根據unique_id列生成groupby對象:

In [207]: gps = df.groupby('unique_id')                                                          

In [209]: gps.groups                                                                             
Out[209]: 
{1: Int64Index([0, 1], dtype='int64'),
 2: Int64Index([2, 3], dtype='int64'),
 3: Int64Index([4, 5, 6, 7, 8], dtype='int64'),
 4: Int64Index([9, 10], dtype='int64')}

我見過pandas迭代組的方法,但這里有一個列表理解。 迭代產生一個元組,帶有 id 和一個數據幀。 我們要測試每個組數據框的“年齡”和“pid”值:

In [211]: recode_values = [(gp['Age']==6).any() & (gp['pid']==1) for x, gp in gps]               
In [212]: recode_values                                                                          
Out[212]: 
[0    False
 1    False
 Name: pid, dtype: bool, 2     True
 3    False
 Name: pid, dtype: bool, 4     True
 5    False
 6    False
 7    False
 8    False
 Name: pid, dtype: bool, 9      True
 10    False
 Name: pid, dtype: bool]

結果是一個系列列表,其中pid為 1,組中有一個“年齡”為 6 的 True。

將這些系列與numpy.hstack會產生一個布爾數組,我們可以將其轉換為整數數組:

In [214]: np.hstack(recode_values)                                                               
Out[214]: 
array([False, False,  True, False,  True, False, False, False, False,
        True, False])
In [215]: df['recode']=_.astype(int)            # assign that to a new column
In [216]: df                                                                                     
Out[216]: 
    unique_id  pid  Age  recode
0           1    1    1       0
1           1    2    3       0
2           2    1    5       1
3           2    2    6       0
4           3    1    6       1
5           3    2    4       0
6           3    3    6       0
7           3    4    1       0
8           3    5    4       0
9           4    1    6       1
10          4    2    5       0

同樣,我認為有一種加入這些系列的慣用熊貓方式。 但現在這有效。

===

好的, groupby 對象有一個apply

In [223]: def foo(gp): 
     ...:     return (gp['Age']==6).any() & (gp['pid']==1).astype(int) 
     ...:                                                                                        
In [224]: gps.apply(foo)                                                                         
Out[224]: 
unique_id    
1          0     0
           1     0
2          2     1
           3     0
3          4     1
           5     0
           6     0
           7     0
           8     0
4          9     1
           10    0
Name: pid, dtype: int64

並刪除多索引:

In [242]: gps.apply(foo).reset_index(0, True)                                                    
Out[242]: 
0     0
1     0
2     1
3     0
4     1
5     0
6     0
7     0
8     0
9     1
10    0
Name: pid, dtype: int64
In [243]: df['recode']=_     # and assign to recode

在這里進行了大量的實驗和學習。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM