【问题标题】:3 data frames and 3 rules in operation to insert data into another dataframe - No common columns - Big data3 个数据框和 3 个操作规则将数据插入另一个数据框 - 没有公共列 - 大数据
【发布时间】:2019-10-26 14:43:02
【问题描述】:

我有 3 个不同的数据帧,可以使用下面给出的代码生成

data_file= pd.DataFrame({'person_id':[1,2,3],'gender': ['Male','Female','Not disclosed'],'ethnicity': ['Chinese','Indian','European'],'Marital_status': ['Single','Married','Widowed'],'Smoke_status':['Yes','No','No']})
map_file= pd.DataFrame({'gender': ['1.Male','2. Female','3. Not disclosed'],'ethnicity': ['1.Chinese','2. Indian','3.European'],
              'Marital_status':['1.Single','2. Married','3 Widowed'],'Smoke_status':['1. Yes','2. No',np.nan]})
hash_file = pd.DataFrame({'keys':['gender','ethnicity','Marital_status','Smoke_status','Yes','No','Male','Female','Single','Married','Widowed','Chinese','Indian','European'],'values':[21,22,23,24,125,126,127,128,129,130,131,141,142,0]})

可以使用下面的代码生成另一个应该填充输出的空数据框

columns = ['person_id','obsid','valuenum','valuestring','valueid']
obs = pd.DataFrame(columns=columns)

我想要达到的目标显示在表格中,您可以在其中看到如何填充数据的规则和描述

我确实尝试过使用 for 循环方法,但是一旦我将其拆开,我就会丢失列名,并且不确定如何进一步进行。

a=1
for i in range(len(data_file)):
   df_temp = data_file[i:a]
   a=a+1
   df_temp=df_temp.unstack()
   df_temp = df_temp.to_frame().reset_index()

我怎样才能让我的输出数据框填充如下所示(ps:我只显示了 person_id = 1 和 4 列)但在实时,我有超过 25k 个人和每个人 400 列。因此,与我的 for 循环不同,任何优雅高效的方法都会有所帮助。

【问题讨论】:

  • 任何其他方法也有帮助

标签: python python-3.x pandas dataframe merge


【解决方案1】:

这是使用DataFrame.meltSeries.map 的替代方法:

# Solution for pandas V 0.24.0 +

columns = ['person_id','obsid','valuenum','valuestring','valueid']

# Create map Series
hash_map = hash_file.set_index('keys')['values']
value_map = map_file.stack().str.split('\.\s?', expand=True).set_index(1, append=True).droplevel(0)[0]

# Melt and add mapped columns
obs = data_file.melt(id_vars=['person_id'], value_name='valuestring')
obs['obsid'] = obs.variable.map(hash_map)
obs['valueid'] = obs.valuestring.map(hash_map).astype('Int64')
obs['valuenum'] = obs[['variable', 'valuestring']].apply(tuple, axis=1).map(value_map)

# Reindex and sort for desired output
obs.reindex(columns=columns).sort_values('person_id')

[出]

    person_id  obsid valuenum    valuestring  valueid
0           1     21        1           Male      127
3           1     22        1        Chinese      141
6           1     23        1         Single      129
9           1     24        1            Yes      125
1           2     21        2         Female      128
4           2     22        2         Indian      142
7           2     23        2        Married      130
10          2     24        2             No      126
2           3     21        3  Not disclosed      NaN
5           3     22        3       European        0
8           3     23        3        Widowed      131
11          3     24        2             No      126

【讨论】:

  • 将很快更新解决方案。目前外出吃午饭
  • 我收到一条错误消息,例如 No attribute 'droplevel'。您能帮我了解一下问题所在吗?
  • 我只是使用相同的语句(value_map)
  • 这是添加到v0.24.0 的 pandas 的新方法....检查您的版本? print(pd.__version__) - 也许只需要升级。如果需要升级,可以从终端运行pip install pandas -U
  • 我遇到了另一个错误“InvalidIndexError: Reindexing only valid with unique value Index objects”
【解决方案2】:

聊天后删除重复数据可以使用:

s = hash_file.set_index('VARIABLE')['concept_id']
df1 = map_file.melt().dropna(subset=['value'])
df1[['valueid','valuestring']] = df1.pop('value').str.extract('(\d+)\.(.+)')
df1['valuestring'] = df1['valuestring'].str.strip()

columns = ['studyid','obsid','valuenum','valuestring','valueid']
obs = data_file.melt('studyid', value_name='valuestring').sort_values('studyid')

#merge by 2 columns variable, valuestring
obs = (obs.merge(df1, on=['variable','valuestring'], how='left')
          .rename(columns={'valueid':'valuenum'}))
obs['obsid'] = obs['variable'].map(s)
obs['valueid'] = obs['valuestring'].map(s)

#map by only one column variable
s1 = df1.drop_duplicates('variable').set_index('variable')['valueid']
obs['valuenum_new'] = obs['variable'].map(s1)

obs = obs.reindex(columns + ['valuenum_new'], axis=1)
print (obs)

#compare number of non missing rows
print (len(obs.dropna(subset=['valuenum'])))
print (len(obs.dropna(subset=['valuenum_new'])))

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-03-12
  • 2021-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多